I have a single activity app (MainActivity) with a dialog fragment. The DialogFragment adds data to the sqllite data base and the MainActivity displays the data in a recycler view. The problem I'm facing is that when I click the "add button" in the DialogFragment and dismisses it, the newly inserted data does not get displayed in the recycler view until the activity gets recreated.
How do I display new data without restarting the app. I have already added "recyclerViewAdapterObject.notifyDataSetChanged" in the DialogFragment class, but it's still not working!
You can solve it by following activity lifecycle method. You just override onResume() method. Put your "data fetching" code and set your adapter inside onResume() method and call onResume() after the data save and before the DialogFragment dismiss. This fix your problem.
But it is not recommended. You should learn to use ViewModel, LiveData.
Example:
override fun onResume() {
super.onResume()
findViewById<RecyclerView>(R.id.rvSocket).also { rv ->
var userList : List<User> = fatchDataFromSQLite()
rv.layoutManager = LinearLayoutManager(this)
rv.setHasFixedSize(true)
adapter = UserAdapter(userList)
rv.adapter = adapter
}
}
Then call onResume() method where you save your data by button click before dismiss your DialogFragment.
Related
I am trying to display data from my Room database on RecyclerView, it works fine except when I fill in new data and try to update my RecyclerView it doesn't update. Here's part of the code that I tried using:
MainActivity.kt
val adapter = MainAdapter(myData)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = adapter
MainAdapter.kt
fun refresh(data: List<NewList>) {
val currentList: MutableList<MyList> = mutableListOf()
currentList.clear()
currentList.addAll(data)
notifyDataSetChanged()
}
I am trying to call this function from Fragment file so it can pass updated list from Room Database (It updates list once someone opens that fragment)
Fragment.kt
var myData = App.instance.db.getAllDao().getAll()
val adapter = MainAdapter(myData)
adapter.refresh(myData)
I printed updated list in the updateData() function and it does show updated list, as well as tried printing ItemCount and it also shows updated ItemCount, but does not update actual display with new data.
The adapter attached to the RecyclerView in MainActivity and in fragment are not same.
just delete adapter creation in Fragment and pass RecyclerView instance to Fragment and then set layout manager and adapter there instead of activity. lastly call updateData method in order to be able to populate adapter.
I have a RecyclerView inside of a Fragment. I use Data Binding and Navigation Component.
My problem is, when I go back to the previous fragment using the back arrow or just navigate back, and after that I open again the fragment, where I have the RecyclerView, the last item will be still there, but the list is totally empty.
I call this method when I close and open the fragment with the RecyclerView.
fun removeAllItems()
{
listOfItems.clear()
notifyItemRangeRemoved(0, listOfItems.lastIndex)
}
I have tried notifyDataSetChanged() also, but still I have the same issue.
Any idea why does it happen?
Thanks.
EDIT:
Finally I could solve the problem.
The onCreate() method:
private lateinit var listItemAdapter: ListItemAdapter
listItemAdapter = ListItemAdapter(context, mutableListOf<ListItem>())
Log.d(TAG, "Size_4: ${listItemAdapter.itemCount}")
listItemAdapter.removeAllItems()
binding.rvCreateNewListFourthItem.apply {
layoutManager = LinearLayoutManager(context)
adapter = listItemAdapter
}
Log.d(TAG, "Size_6: ${listItemAdapter.itemCount}")
Results: Size_4: 0
Results: Size_6: 0
After thse lines I have only 2 setOnClickListeners, which opens 2 other dialogs.
override fun onResume()
{
super.onResume()
Log.d(TAG, "Size_3: ${listItemAdapter.itemCount}")
listItemAdapter.removeAllItems()
Log.d(TAG, "Size_5: ${listItemAdapter.itemCount}")
}
Results: Size_3: 1
Results: Size_5: 0
The solution was to call the removeAllItems() method on the adapter.
When the fragment reached the onResume() method, the list contained the last item from the last session.
enter image description hereI have almost 250 patent item which i want to show in a parent recyclerview. After item click of parent recyclerview it will show over hundreds of data under each parent item in another recycler view. How can i do it like this picture.
I would do it this way. Create an interface:
interface AdapterContract{
fun onListItemClick(id: String) //whatever the parameter is
}
When you instantiate the Adapter in your Fragment1, you can implement this interface:
class Fragment1 : Fragment(), AdapterContract{
...
//when instantiating the adapter:
private val adapter: MyAdapter by lazy{
MyAdapter(this //for the interface)
}
//override the method of Adapter contract
}
Your adapters constructor should look like this: MyAdapter(adapterContract: AdapterContract) : ListAdapter<MyAdapter.MyViewHolder>(Diff_Util_SOME_OBJECT)
Than in the adapters ViewHolder:
itemHolder?.setOnClickListener{
adapterContract.onListItemClick(someId)
}
Now in your override method in Fragment1:
override method onListItemClick(id: String){
//pass this id to the next opening fragment (like Bundles or navargs)
//init `Fragment2` which is going to have all items, that belong to `Fragment1` selected item
}
Load the data :)
I hope you are using a database or something. Should work with hard coded data structures as well, but just to be safe :).
I have 2 activity.
In activity 1, i have a listview show data from database and button Insert
Activity 2 use to add something to database.
When I click button ADD in activity 2, i call method finish() and return to activity 1.
So, somebody can show me how to reload listview in activity 1 please?
Recreating the adapter should help, because you need to get a new dataset as Kaaaarll said.
So for example you have something like this in your code:
MyData data = database.getData();
MyAdapter adapter = new MyAdapter(data);
ListView list = new ListView();
list.setAdapter(adapter);
and in the next run, in the onResume(), get fresh data and reapply the adapter:
MyData data = database.getData();
MyAdapter adapter = new MyAdapter(data);
list.setAdapter(adapter);
You can re-query the database to get the latest data and then repopulate your listview's adapter.
Notify the dataset in the onResume() method activity 1. It should be something like listViewAdapter.notifyDataSetChanged();. Don't forget to check whether they are null or not.
Let me know if it worked.
EDIT:
Something like this should do the work (in activity 1):
#Override
protected void onResume() {
super.onResume();
if (listViewAdapter != null) {
listViewAdapter.notifyDataSetChanged();
}
}
I have a ViewPager with two Fragments. On the first one, there are buttons (it is a menu) and they represent different categories. On the second one, it is a listView which display data.
I am looking for a way to change the data to display on the listView when the user click on one of the menu items.
For example : the user click on the menu item 1 (fragment 1), the listView on the fragment 2 have to be updated with the corresponding data.
I read the documentations from Google Android developer about fragments but I couldn't work it out, I didn't find a solution to my problem.
Maybe I'm missing something ?
EDIT : I tried to clear my ListView by clearing the list of data (ArrayList> listItems) with listItems.clear(). I didn't find how to do adapter.clear(), it seems that this method doesn't exist in the class Adapter.
So to summarize : I created an update method in my fragment which contains the ListView (Fragment2). I called it through a callback method in the main activity, that part seems to work (I checked it with debug mode).
In the update method of my Fragment 2, I clear data with listItems.clear() and then the OnActivityCreated() of the fragment is executed. In it, there is the call of my thread which download data and then it create the ListView in OnPostExecute.
Here is a sample of my code (fragment2) :
// After data are ready
lvListe = (ListView) getView().findViewById(R.id.lvListe);
lvListe.setSelected(true);
lvListe.setScrollingCacheEnabled(false);
adapter = new LazyAdapter(getActivity(),
getActivity().getBaseContext(), listItems,
R.layout.affichageitem, new String[] { "image", "title",
"subtitle" }, new int[] { R.id.img_title,
R.id.titre_main, R.id.soustitre_main });
lvListe.setAdapter(adapter);
lvListe.setClickable(true);
lvListe.setOnItemClickListener(onItemClickListener);
// Update method :
public void update(String requete, String type)
{
this.type = type;
this.requete = requete;
listItems.clear();
}
The way that I would probably do it is to create a callback method in the Activity hosting the ViewPager and also a method in the second Fragment to update the data.
Then you would call it like:
class Fragment1...
{
...
callBackUpdate(data);
}
class Activity...
{
...
public void callBackUpdate(String data)
{
Fragment2.update(data);
}
}
class Fragment2...
{
...
public void update(String data)
{
//do whatever
}
}
The developers page shows how to create a callback method to the Activity.
edit: Actually that's how the Developer's page says to do it. They create the interface OnArticleSelectedListener for the callback.
edit: I'm assuming you are using this library for the LazyLoader: https://github.com/thest1/LazyList
If so, then you can just add the method to clear the data yourself. To do so, add a method like this in ListAdapter:
public void clear()
{
data = new String[](); //depends on what data is, if it's a List then just call data.clear() for example
imageLoader=new ImageLoader(activity.getApplicationContext()); //clear the images
notifyDataSetChanged(); //notify the adapter that the data has changed
}
This might not exactly fit how you currently have it, but you should get the idea.
Try using something known as a FragmentTransaction manager at http://developer.android.com/reference/android/app/FragmentTransaction.html
and also the FragmentManager http://developer.android.com/reference/android/app/FragmentManager.html
Check out some of the questions on stackoverflow related to FragmentManager and FragmentTransaction to figure this out. All you need to do is replace the fragment with a new one which is inflated by a particular xml