setAdapter does not work in fragment Android - android

I used the same code in Activity and it works. But the same thing does not work in Fragment. I have placed some tests to check if the DB is created correctly and found the cursor is filled with data.
Here is the code:
public class Db_fragment extends Fragment {
View view;
ListView listView;
Db_listView_Adapter db_listView_adapter;
public Db_fragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.db_fragment, container, false);
return view;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final MyDatabaseOpenHelper mDbHelper = new MyDatabaseOpenHelper(view.getContext());
final EditText foodName = (EditText) view.findViewById(R.id.nameForDb);
Button enterData = (Button) view.findViewById(R.id.enterData);
Button showData = (Button) view.findViewById(R.id.showData);
enterData.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
SQLiteDatabase myDb = mDbHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(TableFoodMacros.FoodMacros.FOOD_NAME,foodName.getText().toString());
long newRowId ;
newRowId = myDb.insert(TableFoodMacros.FoodMacros.TABLE_NAME,null,contentValues);
Log.e("TEST1","TEST INSERT " + String.valueOf(newRowId));
}
});
showData.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
SQLiteDatabase myDb = mDbHelper.getReadableDatabase();
String[] projection = {"_id",TableFoodMacros.FoodMacros.FOOD_NAME};
Cursor c = myDb.query(
TableFoodMacros.FoodMacros.TABLE_NAME,
projection,
null,
null,
null,
null,
null,
null
);
Log.e("TEST3", String.valueOf(c.getCount()));
listView = (ListView) view.findViewById(R.id.dbView);
db_listView_adapter = new Db_listView_Adapter(view.getContext(),c);
listView.setAdapter(db_listView_adapter);
}
});
}
}
The app crashes on this line :
listView.setAdapter(db_listView_adapter);

You need to remove the findViewById of the dbView from the onClickListener of showData and place it in the onCreateView.
So remove the following.
showData.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// ... Remove the following code segment from here.
listView = (ListView) view.findViewById(R.id.dbView);
db_listView_adapter = new Db_listView_Adapter(view.getContext(),c);
listView.setAdapter(db_listView_adapter);
}
});
Place the code segment in your onCreateView function.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.db_fragment, container, false);
// Place the code segment here
listView = (ListView) view.findViewById(R.id.dbView);
db_listView_adapter = new Db_listView_Adapter(view.getContext(),c);
listView.setAdapter(db_listView_adapter);
return view;
}
It works in your Activity as you don't have find the ListView id in the View returned. Once you set the content view of your Activity you can place findViewById anywhere and it'll find the associated layout reference perfectly.
In case of Fragment, as you see the onCreateView function returns a View object as the reference of the View which is inflated. So you need to find your ListView in that View. That's why you need to put view.findViewById to search for reference id of the ListView in that View which is inflated.
When you're putting the listView = (ListView) view.findViewById(R.id.dbView); inside the showData.setOnClickListener it gets the reference of the button showData and tries to find the dbView in that Button view which causes the error.
So its necessary to get the reference of your list inside onCreateView and set the adapter there. You can then easily call notifyDatasetChanged() to reload your list when the cursor is filled with data.
By the way, you may put the code segment in your onViewCreated function too as you see you could get the reference of the showData button from there without any problem. So you can even put the code segment there too.
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final MyDatabaseOpenHelper mDbHelper = new MyDatabaseOpenHelper(view.getContext());
final EditText foodName = (EditText) view.findViewById(R.id.nameForDb);
Button enterData = (Button) view.findViewById(R.id.enterData);
Button showData = (Button) view.findViewById(R.id.showData);
// You can place the code segment here too
listView = (ListView) view.findViewById(R.id.dbView);
db_listView_adapter = new Db_listView_Adapter(view.getContext(),c);
listView.setAdapter(db_listView_adapter);
// ... Other code goes here.
}
And you might modify the showData.setOnClickListener like this
showData.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
SQLiteDatabase myDb = mDbHelper.getReadableDatabase();
String[] projection = {"_id",TableFoodMacros.FoodMacros.FOOD_NAME};
Cursor c = myDb.query(
TableFoodMacros.FoodMacros.TABLE_NAME,
projection,
null,
null,
null,
null,
null,
null
);
Log.e("TEST3", String.valueOf(c.getCount()));
// Call notifyDatasetChanged when the cursor is filled with data to load the list.
db_listView_adapter.notifyDatasetChanged();
}
});

Related

Android reload swap cursorAdapter to do a listView refresh

Hello I am a beginner in Android programming and I have a problem with refreshing listView.
I am using CURSORADAPTER to show data in the listView, and my problem is about refreshing the cursor to show newly inserted data!!!
I read a lot of similar problems here on StackOverflow, and I see that others talk about swapCursor() or changeCursor(), or adapter.notifyDataSetChanged(); or requery()-DEPRECATED, but I really don't know how to do that.
I am struggling with this problem for five days now, and I really try to find some example on the web but I haven't found anything that I understand for now.
Then I made other simple app which use only two fragments, db and a listView.
On the first fragment (FragmentA) the only thing I do is insert some data in my db, on second fragment ``(FragmentB)` I have a listView that shows data from my db.
When I insert data in db on my FragmentA, and then go to second fragment FragmentB I do not get newly inserted item from db in my listView, and I do understand why, because of the android lifecycle onCreateView method from fragmentB was already called once when I started application, and cursor was loaded with data from db, and when I close and restart application then I get new data from db because cursor was "reloaded" when onCreateView was called again. I have all of this Override methods: onCreateView, onAttach, onCreate, onActivityCreated, onStart, onResume, onPause, onStop, onDestroyView, onDestroy, onDetach but none of these methods were called again when I use only 2 fragments and this is also what I understand why is happening, so I used viewPager.addOnPageChangeListener method to try to refresh cursor when FragmentB was loaded.
I also found some unanswered questions on this topic, so I think, maybe that the answer to my question can contribute to others on the StackOverflow community in the future.
THANK YOU ALL VERY MUCH!!!
This is my code:
MainActivity:
public class MainActivity extends AppCompatActivity {
ViewPager viewPager;
DatabaseAdapter databaseAdapter;
private static final String TAG = MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.pager);
FragmentManager fragmentManager = getSupportFragmentManager();
final MyFragmentAdapter myFragmentAdapter = new MyFragmentAdapter(fragmentManager);
viewPager.setAdapter(new MyFragmentAdapter(fragmentManager));
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
Log.d(TAG, "onPageScrolled position " + position); ////THIS IS WHERE I THINK CURSOR SHOULD BE REFRESHED SOMEHOW
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
}
FragmentA :
public class FragmentA extends Fragment {
EditText editText;
Button button;
DatabaseAdapter databaseAdapter;
private static final String TAG = FragmentA.class.getSimpleName();
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
Log.d(TAG, "onCreateView 1");
View view = inflater.inflate(R.layout.fragment_a, container, false);
editText = (EditText) view.findViewById(R.id.editText_insert);
button = (Button) view.findViewById(R.id.button_insert);
databaseAdapter = new DatabaseAdapter(getContext());
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String tableName = "profit";
double price = 2;
String insTxt = String.valueOf(editText.getText());
Log.d(TAG, "button click = " + insTxt);
add(tableName);
}
});
return view;
}
//for insert into db
public void add(String tableName){
long id = databaseAdapter.insertData(tableName);
if (id < 0){
Log.d(TAG, "BAD INSERT");
}else {
Log.d(TAG, "INSERT OK!!!!");
}
}
}
FragmentB
public class FragmentB extends Fragment{
private static final String TAG = FragmentB.class.getSimpleName();
ListView listView;
EditText editText;
Button button;
//list view PART
MyCustomAdapter myCustomAdapter;
DatabaseAdapter databaseAdapter;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_b, container, false);
Log.d(TAG, " FragmentB onCreateView 1");
databaseAdapter = new DatabaseAdapter(getContext());
listView = (ListView) view.findViewById(R.id.listView);
Cursor cursor = databaseAdapter.cursorLoadingData(); // populate cursor
myCustomAdapter = new MyCustomAdapter(getContext(), cursor);
listView.setAdapter(myCustomAdapter);
return view;
}
}
DatabaseAdapter :
public class DatabaseAdapter {
.....
//part for taking all data from db...
public Cursor cursorLoadingData(){
SQLiteDatabase db = databaseHelper.getWritableDatabase();
String myQuery = " select * from profit order by _id desc";
Cursor cursor = db.rawQuery(myQuery, null);
return cursor;
}
.....
}
MyCustomAdapter - CursorAdapter class:
public class MyCustomAdapter extends CursorAdapter {
private static final String TAG = MyCustomAdapter.class.getSimpleName();
public MyCustomAdapter(Context context, Cursor c) {
super(context, c);
}
public MyCustomAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.custom_list_item, parent, false);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
TextView textViewId = (TextView) view.findViewById(R.id.textView_id);
long ExtractedId = cursor.getLong(cursor.getColumnIndexOrThrow("_id"));
textViewId.setText(String.valueOf(ExtractedId));
}
}

Call a function defined in a fragment, from the main activity that required a view

I have a function in a fragment (Frag_Lista) that changes its cardView dynamically using the output of a query.
The first time i call it from that fragment and it works. The second time i would call it from the main activity, but i can't set correctly the second parameter, the view.
Frag_Lista
public void function_in_fragment() {
//some code
Context context = getActivity();
DBhelper database = ((MainActivity)getActivity()).getDatabase();
Cursor cursor=database.ottieni_tutto();
genera_lista(cursor,getView());
}
public void genera_lista(Cursor cursor, View v) {
list.clear();
if(cursor!=null) {
if(cursor.moveToFirst()) {
while (!cursor.isAfterLast()) {
//Log.d(TAG,cursor.getString(cursor.getColumnIndex(DBhelper.COL_NOME)));
String nome = cursor.getString(cursor.getColumnIndex(DBhelper.COL_NOME));
String tipo = cursor.getString(cursor.getColumnIndex(DBhelper.COL_TIPO));
String difficolta = cursor.getString(cursor.getColumnIndex(DBhelper.COL_DIFFICOLTA));
String immagine = cursor.getString(cursor.getColumnIndex(DBhelper.COL_IMMAGINE));
Food_Card food_card = new Food_Card(immagine, nome, tipo, difficolta);
list.add(food_card);
cursor.moveToNext();
}
cursor.close();
}
else Log.d(TAG,"Cursor vuoto");
}
else Log.d(TAG,"Cursor nullo");
recyclerView = (RecyclerView) v.findViewById(R.id.recyclerView);
layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
adapter=new food_adapter(getActivity(),list);
recyclerView.setAdapter(adapter);
}
MainActivity
public void function_in_mainActivity(String[] parametri) {
Cursor cursor=database.query_filtri(parametri);
Frag_Lista nothing=new Frag_Lista();
View v= ?
nothing.genera_lista(cursor,v);
}
How can i pass correctly the current view?
Frag_Lista
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.frag_lista, container, false);
setHasOptionsMenu(true);
return(v);
}
Change your onCreateView like this
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.frag_lista, container, false);
recyclerView = (RecyclerView) v.findViewById(R.id.recyclerView);
setHasOptionsMenu(true);
return(v);
}
Crate a field inside your Fragment for recyclerView.
Now you always have a reference to the RecyclerView and don't need to pass it as a argument to the method.
public void genera_lista(Cursor cursor)

Start Fragment from Activity or save data and return to previous Fragment

I am using nav drawer. So i need from Fragment start Activity in which i start another Activity where i have ListView,clicking on which i must save data.
After save i need to return to Fragment where saved Data must be showing.
So here is my Fragment
public class ArmoryFragment extends Fragment {
public ArmoryFragment(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_armory, container, false);
Button button = (Button) rootView.findViewById(R.id.button_rifles);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getActivity(), Rifles.class);
startActivity(intent);
}
});
return rootView;
}
}
and here is my activivty from where i need to return
public class Rifles extends Activity implements View.OnClickListener, OnItemSelectedListener {
DatabaseHelper db;
String BrandModel;
private RifleDAO rifleDAO;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.rifles);
initList();
this.rifleDAO = new RifleDAO(this);
ListView listView = (ListView) findViewById(R.id.listView1);
SimpleAdapter simpleAdapter = new SimpleAdapter(this, riflesList, android.R.layout.simple_list_item_1, new String[] {"rifle"}, new int[] {android.R.id.text1});
listView.setAdapter(simpleAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
String item = ((TextView)view).getText().toString();
Toast.makeText(getBaseContext(), item, Toast.LENGTH_LONG).show();
BrandModel= ((TextView)view).getText().toString();
String[] parts=BrandModel.split(" ");
String Brand=parts[0];
String Model = parts[1];
// need to return from somewhere here
}
});
} next is parser code... supose it is not needed
So how can I return from Activity to Fragment?
Well if you want to save data, I prefer adding the data to a table in your database (obviously you have a databaseHelper class so make you own table) and when you are back from your activity put extra a position you want and call :
selectItem(mCurrentSelectedPosition);
so mCurrentSelectedPosition is the position of the fragment that you want to be selected.

onClickListener in ListFragment not responding

Confused as to why the onClickListener is not responding. Is it because but buttons are set in one layout, but bound to another one? Any help would be appreciated.
public class ActivityList extends ListFragment
{
private ActivityDbAdapter mDbHelper;
private Long mRowId=Long.valueOf(1);
private Activity mContext; //changed to private
AlertDialog activity_relationship;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mContext=this.getActivity();
mDbHelper=new ActivityDbAdapter(mContext);
mDbHelper.open();
Cursor activity = mDbHelper.fetchAll(mRowId);
View view = (View) inflater.inflate(R.layout.activity_activity_row, container,false);
Button relationship = (Button) view.findViewById(R.id.show_relationship_activities);
String[] from = new String[]{ActivityDbAdapter.COLUMN_NAME_VALUE1_RELATIONSHIP , //from and too.
ActivityDbAdapter.COLUMN_NAME_VALUE1_EDUCATION,
ActivityDbAdapter.COLUMN_NAME_VALUE1_RECREATION,
ActivityDbAdapter.COLUMN_NAME_VALUE1_MIND, ActivityDbAdapter.COLUMN_NAME_VALUE1_DAILY};
int[] to = new int[]{R.id.relationship_value,R.id.education_value, R.id.recreation_value,
R.id.mind_value, R.id.daily_value};
SimpleCursorAdapter contacts =
new SimpleCursorAdapter(mContext, R.layout.activity_activity_row, activity, from, to); //my cursor adapter
relationship.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg) {
Log.e("Why","Are you not working?");
Cursor activity = mDbHelper.fetchAll(mRowId);
String mactivity_relationship=activity.getString( //define all of the Strings. Gahh!!
activity.getColumnIndexOrThrow(ActivityDbAdapter.COLUMN_NAME_ACTIVITY1_RELATIONSHIP));
AlertDialog activity_relationship=new AlertDialog.Builder(mContext).create();
activity_relationship.setTitle("Relationship Activities");
String activities=(mactivity_relationship+"\n"+mactivity_relationship2+"\n"+mactivity_relationship3+
"\n"+mactivity_relationship4+"\n"+mactivity_relationship5);
activity_relationship.setMessage(activities);
activity_relationship.show();
}
});
setListAdapter(contacts);
return inflater.inflate(R.layout.activity_activity_list, container, false);
}
}
As I have it right now, the log is not even showing up.
You may want to return the view that you actually create(and use for getting the Button) in the onCreateView:
//...
return view;
instead of returning a newly inflated layout(and losing the previous Button):
return inflater.inflate(R.layout.activity_activity_list, container, false);
Or add the view to a view from the R.layout.activity_activity_list file that you inflate and return.

Android error passing context to Cursor Adapter inside OnClick(View view)

Inside a fragment, I have a button which I want to "trigger" the filling of a Listview from a database, using a Cursor Adapter.
The code for the fragment goes something like this:
public class TabFragment6 extends ListFragment {
/** (non-Javadoc)
* #see android.support.v4.app.Fragment#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
LinearLayout Layout6 = (LinearLayout) inflater.inflate(R.layout.tab_frag6_layout, container, false);
// Register for the Button.OnClick event
Button bShopGuit = (Button)Layout6.findViewById(R.id.buttonshopguit);
bShopGuit.setOnClickListener(new View.OnClickListener() { //abre setonclicklistener(
#Override
public void onClick(View v) {
Cursor allItems;
MyDatabase db;
Context ctx = (Context)TabFragment6.this.getActivity();
db = new MyDatabase(ctx);
allItems = db.getGuitarItems();
ListAdapter adapter = new SimpleCursorAdapter (ctx,
android.R.layout.simple_list_item_1,
allItems,
new String[] {"ItemName"},
new int[] {android.R.id.text1});
getListView().setAdapter(adapter);
}
}); //fecha )
return Layout6;
}
However, I'm getting an error in the adapter: The method getactivity() is undefined for the type new View.OnClickListener(){}
How can I fix this? Thanks!!
use this db = new MyDatabase(getActivity()); instead of Context ctx = (Context)TabFragment6.this.getActivity(); and db = new MyDatabase(ctx);
You cannot call getActivity() in the new View.OnClickListener() { interface
for it doesn't have this method there. you may probably want to create final reference
to your activity and use it within your onClick() method.
You are creating a new anonymous class which implements View.OnClickListener interface which
doesn't have getActivity() method.
should be something like this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
LinearLayout Layout6 = (LinearLayout) inflater.inflate(R.layout.tab_frag6_layout, container, false);
final Activity activity = this.getActivity(); //this will call your tabfragment's associated activity
............
//and in your onClick()
db = new MyDatabase(activity); // or try to use the Contexts or cast to them depends on your constructor parameters
hope it helps

Categories

Resources