RecycleView update dataset and adapter from another fragment - android

I'm on a fragment activity that have 3 fragments. each fragments implement Recycle-view and it's adapter. I wanna delete from a list and then update another fragment lists but I have problem in this.
public void deleteIt(View v) {
ZeroActivity.dao.deleteMessages(serverId); // delete the mesage from DB
switch (TransactionActivity.current_tab) {
case 0:
ZeroActivity.itemData_1.remove(data_list_position); // delete the message from arrayList
ZeroActivity.recycleViewAdapter1.notifyItemRemoved(data_list_position); //remove message from Adapter
break;
case 2:
but always after first deletion and select final item app crashes and get this error:
Invalid index 4, size is 3
It seems that problem is with index of Adapter and Arraylist that wont match!

You are removing two times with same index value thats why you are getting error in second time.. just do this . i hope it will work
ZeroActivity.itemData_1.remove(data_list_position); // delete the message from arrayList
ZeroActivity.recycleViewAdapter1.notifyDataSetChanged();
or call only this line
ZeroActivity.recycleViewAdapter1.notifyItemRemoved(data_list_position)

I finally solve this problem by refresh Recycle-view item counts by adding:
notifyItemRangeChanged(data_list_position, newsize);
it seems that Recycle-view needs to update it's list count after remove or adding new items.
ZeroActivity.itemData_1.remove(data_list_position); // delete the message from arrayList
ZeroActivity.recycleViewAdapter1.notifyItemRemoved(data_list_position); //remove message from Adsapter
ZeroActivity.recycleViewAdapter1.notifyItemRangeChanged(data_list_position, ZeroActivity.itemData_1.size());

Related

Item inserted at first position is not visible until scrolling up

Scenario:
my adapter supports two different view types: A & B
the adapter is notified about 100 items of type A - everything is rendered correctly
the adapter is notified about one item of type B insertion using
notifyItemRangeInserted at position 0 - this item is "invisible"
by default and in order to see it I have to manually scroll up.
How can I get this first item of type B "automatically" visible?
You can use this line of code after notify item of type B:
yourRecyclerView.smoothScrollToPosition(0);
using https://stackoverflow.com/a/54899984/8144663 only wont resolve your issue.
You will need to call smoothScrollToPosition() in the next frame like,
recyclerview.post(new Runnable() {
#Override
public void run() {
recycleview.smoothScrollToPosition(n);
}
});

How to prevent double items but also prevent entire list from refreshing?

I am getting a JSON Array of user ids strings from a database:
["uid1", "uid103", "uid322"]
I am fetching this array on a time triggered loop, and I use notifyDataSetChanged with myDataSet.clear() to display the list, and to prevent duplicates. The problem with this method is that the list is constantly "refreshing", and I just want to either add or remove the items that's needed to be removed or added.
If I remove the clear() part, then the list won't refresh, but I will get duplicate items.
This is how the code (+pseudo) looks like:
trigger(just a time based loop) {
myDataset.clear();
jsonArray = //the id array from the database;
for (int i=0;i<jsonArray.length;i++){
myDataset.add(new User(jsonArray.get(i), imageUrl));
mAdapter.notifyDataSetChanged();
}
}
You can use for this purpose DiffUtil class (Medium example).
It calculates differences between new and old datasets and updates it.
But if you don't want to deep dive into DiffUtil you can try to use combination of notifyItemInserted() and notifyItemChanged()
You need to compare the 2 lists before refreshing. So,
If an item is removed, Your list's size will be smaller.
If an item is added, the list's size will be bigger and the new item will be the last item in the retrieved array.
But if an item is removed and at the same time an item is added, your list's size will be the same but the last item will change.
So, you need to check both array size and the last item before refreshing like this:
trigger(just a time based loop) {
if((myDataset.size() != jsonArray.size()) || myDataset[last] != jsonArray[last]) {
myDataset.clear();
jsonArray = //the id array from the database;
for (int i=0;i<jsonArray.length;i++){
myDataset.add(new User(jsonArray.get(i)));
mAdapter.notifyDataSetChanged();
}
}
}
Change your code as below, Your loop will do all the changes in your data and once the loop is over you notify those changes to your list in one go, instead of refreshing it each time.
for (int i=0;i<jsonArray.length;i++){
myDataset.add(new User(jsonArray.get(i)));
}
mAdapter.notifyDataSetChanged();
If you want to avoid duplicates use Set, add items to set from your json array and use it as datasource for your list.
You have a basic misunderstanding of the timer trigger. The loop will not pause there waiting for your next User entry from JSON. So adding notify in the loop is very bad practice. One notify outside the loop is enough. If a new User is added, it should appear in another timer trigger, i.e., another loop.
If you are seeing duplicate, that must be in the code handling the JSON to insert your database. However this code is not listed here so you need to look at that code.
Adding a unique index in the database table is a good solution.
for avoiding duplicate use contains
myDataset.clear();
for (int i=0;i<jsonArray.length;i++){
User user=new User(jsonArray.get(i), imageUrl);
//now check if its already in list or not by using contains.
if(!myDataset.contains(user)){
myDataset.add(user)
}
}//end of loop
and then pass list to your adapter and then call notifyDataSetChanged()
mAdapter.notifyDataSetChanged();

NotifyItemRemoved throws an exception

I have this kind of problem. I have a simple app for wallpapers.
I am getting wallpapers from API, there is a Tab called Category in which I have Sections I would like to hide few of that Sections inside Category Tab.
In the best scenario my backend developer have to hide or remove it from backend but as he is not available now. I have decided to do it myself.
So, in RecyclerView for Category Tab in onBindViewHolder I am checking if the title is equal the one that I want to be deleted I am calling removeAt (you can see that part below):
if (categoryTitle.equals("Hot")) {
list.removeAt(holder.layoutPosition)
}
I need this to be called whenever the Category Tab shows so the user will not be able to see that Category Section. But it doesn't update it because I have to call this two methods as well:
if (categoryTitle.equals("Hot")) {
list.removeAt(holder.layoutPosition)
notifyItemRemoved(holder.layoutPosition)
notifyItemRangeChanged(holder.layoutPosition, list.size)
}
but while call them I got en error saying
"Cannot call this method while RecyclerView is computing a layout or scrolling . . ."
Here is the question.
Where I have to call it to avoid the error ?
(link of my app:
https://play.google.com/store/apps/details?id=com.backpaper)
(please do not suggest to use timer or delay or something similar (-_-) )
Update:
override fun onResponse(categories: Categories) {
categories.categories!!.removeAt(5)
categories.categories!!.removeAt(1)
adapter = RecyclerViewAdapterC(categories.categories!!)}
Do not remove item in onBindViewHolder() It will throw exception because item is not added yet . Exception will be as.
java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling
You should remove the item from dataset before adding them to adapter .
if (!categoryTitle.equals("Hot")) {
// Add item else do not add item
}
After filtering the list dataset then set adapter with filtered list .
below is an example .
ArrayList<String> list=new ArrayList();
for(String cat : categories.categories){
if (!categoryTitle.equals("Hot")) {
list.add(cat);
}
}
adapter = RecyclerViewAdapterC(list)

ListView increasement and adapter changed dynamically

Friends. I am new android developer and asking question .I have searchd a lot,but didn't get the desired result.So, Here's my problem.
1. I have a ListView that conations a number of items
ListView
_________
item1
item2
item3
_________
2. When I click onItem click Listener, I get all the values of item conation(ItemDetail.java)
3. Now I have two buttons in (ItemDetail.java) buttonNext and buttonPrevious
so my query when I click buttonNext and buttonPrevious my listview item detail from list should be changed dynamically increment and decrement of position.
Thanks in advance friends.
You have to code on onResume of that List Activity.
Just update your adapter with the newly sorted data as you want and refresh the listview with that new data.
In case of any query, let me know.
Hope you got my point.
Did you try this:
OnClick() change collection elements order of the list you used in adapter (list that is binded). SwapElements(list, index1, index2)
you need to use runOnUiThread() to bind data of UI components.
runOnUiThread(new Runnable() { public void run() { refreshListview() } });
refreshListview() method is the one you are using for your refresh routine.

How to refresh cursorAdapter especially when deleting last item in a list?

How to refresh cursorAdapter especially when deleting last item in a list?
scenario:
working:
editing list-view row, OK
adding list-view row, OK
deleting list-view row(one by one), until one is left, OK
problem:
deleting the last row/item, FAILED;
you need to close first your activity and open it again for it to refresh.
I am using a cursor adapter, and I want to refresh its list when deleting the last row/item of a list view. my method for refreshing an adapter is to assign a new instance of cursorAdapter to my Listview(as if, doing this again and again).
code:
listview.setAdapter(new ImmunizationListCursorAdapter(
this,// current activity
R.layout.imm_list_row,// layout for each row
immunizationCursor,// the data
// Pass in the cursor to bind to.
// Array of cursor columns to bind to.
new String[] { ImmunizationModel.IM_COL_VACNAME,
ImmunizationModel.IM_COL_DATE },
// Parallel array of which template objects to bind to
// those
// columns.
new int[] { R.id.text_vaccine_name,
R.id.text_date_description }));
there it is.
any one who can help me? :((
All you need to do is to call productCursor.requery() after each modification to the dataset.
requery() automatically triggers execution of your query (in order to retrieve the new data) plus notification to the ListView (by the adapter) that it has to refresh itself.
BTW, until not so long ago I was using the same wrong method of assign a new instance of CursorAdapter...

Categories

Resources