LiveData is duplicating MutableList - android

I want to update my Recyclerview items whenever there is a data change in Firestore.
So my activity have the following code:
taskViewModel.fetchedTaskLiveData.observe(
this, Observer {
if (it != null) {
todoListAdapter.setListData(it)
showRecyclerView()
}
Inside adapter setListData method:
fun setListData(data: MutableList<Todo>) {
//this.todoList.clear()
this.todoList.addAll(data)
notifyDataSetChanged()
}
In this situation, whenever a changed list is fetched, Recyclerview is duplicating and adding the changed
list below the old list.
And if "this.todoList.clear()" is uncommented, list is getting cleared and no data is showing on data change.
I tried all possible solutions, but I think somewhere am missing a part. stuck since a long time.
Thanks a lot for all kind of suggestion.

So I was stuck with this and found out after 12 hours a tiny change.
I corrected it by changing for with forEach and that changed the game.
Also I am clearing list items before adding the items.
todoList.clear()

Related

Android|Kotlin recyclerView update one item

I have this issue:
I'm using a recycler view in my app but the thing is that I need to update one single item of my recycler view.
When I click on the recycler view item, it sends me to another screen where I update the value and returned (this is working, I get the values on back)
I tried to add a new function inside my adapter as follows:
public fun updateItem(updatedOI: ArrayList<OrderItem>){
orderItem = updatedOI
notifyDataSetChanged()
}
and then call the function from my fragment/activity but it is not working.
I basically need to grab the index somehow and update that single index what it is doing now is removing all of the items and just add the updated one.
How do I fix this issue?
The problem is you can't update the data by making it reference another.
fun update(items: List<OrderItem>) {
orderItem.clear()
orderItem.addAll(items)
notifyDataSetChanged()
}
I'm using a list here because it is easier than working with arrays, your inner data should be a mutable list.
If you only want to update 1 item. You can get the index and then pass it back
//in the fragment/activity
intent.putExtra(INDEX, youClickedIndex)
and then set the result back like you are allegedly doing
fun update(item: OrdertItem, index: Int) {
orderItem.add(index, item)
notifyItemChanged(index)
}

data binding to list size is not working?

I have an android app that shows a screen to the user to enter data if a List is empty, otherwise it shows the List in a recyclerview.
When the app first starts this works fine. The data must be read from an online database so the empty list text shows until the data is loaded and then the list shows. If I delete the entries from the database using the app the List size goes to zero, but the empty list does not show, the Recyclerview remains visible (but empty sine the List is empty.
The binding for the empty textview is:
android:visibility="#{list.size() == 0 ? View.VISIBLE : View.GONE}"
and for the recyclerview is:
android:visibility="#{list.size() == 0 ? View.GONE : View.VISIBLE}"
The List is bound using:
binding.setList(mList) ;
As I said the startup of the app works so I don't understand why having the list go to empty does not also work.
Any pointers would be much appreciated.
It seems like you are not triggering the "binding update" after deleting items from database. Anyway you could approach it differently, using let's say LiveData<Boolean> or ObservableBoolean that would say wheter list is empty or not, your binding expression would not change.
The advantage of using LiveData or Observable<T>with dataBinding is that everytime you change the value of these it is "propagated" to the view automatically - so you dont need to do this binding.setList(mList); each time view should update. There is also ObservableArrayList, binding that instead of regular List might work too, but I haven't tried that.
see using observables with databinding
By the way the LiveData + databinding works even better if you place your LiveData into a ViewModel and bind from xml to that.

Android RecyclerView.Adapter notifyItem drives me crazy

I searched for hours but still have no explanation (even not in official docu) what is the right way to use a RecyclerView.Adapters' notify-methods. Already read a lot of similar question on SO, but no could solve my simple problem. I try to put down a short, simplified example.
class MyAdapterClass extends RecyclerView.Adapter<MyAdapterClass.MyViewHolderClass> {
...
List myItemList = new ArrayList<MyItemType>();
...
}
RecyclerView myRecView = (RecyclerView) findViewById(R.id.myRecView);
myRecView.setAdapter(new MyAdapterClass(...)));
Even when inserting the first item, the view is not refreshed.
myAdapter.myItemList.add(newItem);
myAdapter.notifyItemInserted(myAdapter.myItemList.size() - 1);
If I then tightly touch (try to scroll) the 1-item-listview, the item appears. So it seams to be a refreshing issue. But why? I have an emtpy list, then I insert one item, then I notify the adapter about the insertion. Whats wrong with my expectation?
By the way, even if I additionally call:
myAdapter.notifyItemChanged(myAdapter.myItemList.size() - 1);
it gets not automatically refreshed.
EDIT: And of course, I dont want to use notifyDataSetChanged() :-) only insert, update, remove on an existing list.
Try to add this code inside your adapter class :
#Override
public int getItemCount() {
return myItemList.size();
}
i hope you define in adpter getItemCount() in list size. then used blow code for notify adapter.
myadapter.notifyItemRangeChanged(0, userDataArrayList.size());

notifyDataSetChanged() not being called when underlying Realm is changed using RealmRecyclerViewAdapter

I have a set of data in a Realm that is displayed in a RecyclerView using a RealmRecyclerViewAdapter. Basically, I'll have 25 elements displayed in the RecyclerView -- if items are being inserted into the Realm for the first time there are no issues. It seems to work properly if the Realm isn't being added to shortly after all its data has been deleted because the issue only arises when I need to delete all the items in the Realm and then add a new Collection of items shortly afterwards.
What will happen is I will send an http request for the new items, and on receiving them, I'll delete all the items currently in the Realm, and then add the new ones, both in different transactions; I've also tried doing it in the same transaction.
The unexpected behavior is that the contents of the RecyclerView will flicker for a very brief moment, as if all the items are about to be rebound, and I can even see the data of the new items being shown for a split second, but then the contents of the RecyclerView just goes back to showing the previous data -- the data I know to be deleted from the Realm. I know it's deleted because if I interact with the RecyclerView after this flicker, even just a click on a static view, all the items will be instantly rebound and reflect the new items that have been added; as if notifyDataSetChanged() is finally being called.
This behavior isn't always exhibited. Most of the time the items are all deleted, the new ones are added, and it just works perfectly; no flicker. But as far as the user behavior goes when it works properly and when it doesn't, there is nothing different. The same thing can be done over and over again and sometimes it will work and other times it won't.
I've tried deleting the items using mRealm.deleteAll() and mOrderedRealmList.deleteAllFromRealm(). And I've tried adding the items to the collection using both mRealm.insert(items) and mRealm.copyToRealm(items). I've also tried manually calling notifyDataSetChanged() only after the items are added, only after the items are all deleted, and after both events, but the issue still occurs.
Any idea on what could be causing this behavior?
This is the only code that is run that manipulates Realm data:
mRealm.beginTransaction();
mOrderedRealmCollection().deleteAllFromRealm();
mRealm.commitTransaction();
...
...
processing of new items...
...
...
mRealm.beginTransaction();
mRealm.insert(items);
mRealm.commitTransaction();
Update:
When I delete all the items from the Realm and add the new items within the same transaction the unexpected behavior occurs more frequently. Also, I've noticed that when the changes are made in the same transaction and the issue occurs, sometimes there is no flicker, the RecyclerView just continues to display the old data, uninterrupted, but if I touch the RecyclerView anywhere, just like when the flicker does occur, all the items will be instantly rebound and reflect the new items that have been added.
Update: How Adapter is Set Up
//in onCreate() method
mItems = mRealm.where(Item.class).findAllSorted("mIndex", Sort.ASCENDING);
//in onCreateView() method
mRecyclerView.setAdapter(mAdapter = new MyRealmRecyclerViewAdapter(this, mItems));
Update: Cancel Button onClick() Code
private void setListeners(){
mCancelButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mSearchEditText.clearFocus();
mCancelButton.setVisibility(View.GONE);
mCreateItemButton.setVisible(true);
Toast.makeText(A_Main.this,"Cancel clicked",Toast.LENGTH_SHORT).show();
}
});

Strange ListView behaviour on data set change

In my application I'm using number of items checked on list.
I'm also updating items on list, deleting them and inserting new ones.
Case scenario:
I'm removing item from list used by adapter
I'm calling notifyDataSetChange
I'm refreshing my component
My component is asking mMyListView for number of checked items
View is returning old number
I was browsing android sources and find out that even if I call notifyDataSetChange, handleDataChanged method (some package-protected AbsListView method) is not call immediately, but later. And this is the function responsible for changing number of checked items.
I resolved it by extending ListView with my own class with only one change:
#Override
public long[] getCheckedItemIds() {
handleDataChanged();
return super.getCheckedItemIds();
}
To get checked items number, I'm calling mMyListView.getCheckedItemIds().length (because of API level I cannot use getCheckedItemCount).
Now it works, but I don't like this solution. Am I missing something here?

Categories

Resources