Purpose of associated data with ListView footer in Android? - android

What is the purpose of the associated data with the Android ListView footer? There is a method to add the footer view to a ListView
void addFooterView (View v, Object data, boolean isSelectable)
And the documentation on this parameter says:
Data to associate with this view
However, the documentation did not describe what it actually does. So, what effect does the data parameter have?

The Object data returned from Adapter's getItem method.
By documentation:
Add a fixed view to appear at the top of the list. If this method is called more than once, the views will appear in the order they were added. Views added using this call can take focus if they want.
Note: When first introduced, this method could only be called before setting the adapter with setAdapter(ListAdapter). Starting with KITKAT, this method may be called at any time. If the ListView's adapter does not extend HeaderViewListAdapter, it will be wrapped with a supporting instance of WrapperListAdapter.
Parameters:
v View: The view to add.
data Object: Data to associate with this view
isSelectable boolean: whether the item is selectable
Then
From the Adapters documentation
getItem Added in API level 1
Object getItem (int position)
Get the data item associated with the specified position in the data set.
Parameters
position int: Position of the item whose data we want within the adapter's data set.
Returns
Object The data at the specified position.

Related

How to check if item in RecyclerView Adapter is still visible after async callback

I want to update one item calling asynchronous call to server API inside onBindViewHolder. I send item at position + position into the callback. Response call arrives in 20 seconds into callback funcion. Into the callback function is returned response and position. Then I call notifyItemChanged(pos, response). And inside payload onBindViewHolder I update item on that position and its View. Problem is that if async request takes 20 seconds and user will scroll quickly throught RecyclerView it will update wrong item View because that view at position could be unbound or could be bound to other item from list.
Is there any way how to track which item at which position is unbound to cancel request? I have to update this one info after adapter is created, because if I will do that before, user will not see any recyclerView item for almost 2 minutes till my list is ready. (only this one call is taking so long).
I wouldn't pass the position as context. I would pass an identifier. Could be an internal integer as id or something. Then you can easily determine which id's are currently visible on the screen and see if that list contains the id of the calback.
I am not sure about your question, but you could work onto your items directly in your adapter.
Then you do:
Adapter adapter = new BaseAdapter(newDataset);
recyclerView.setAdapter(adapter);
recyclerView.notifyDataSetChanged();
Otherwise, if your really work on views rather than dataset, you can do this:
in your adapter:
create a View array
create a custom function View getViewAtPos(int pos)
check if your view is visible in your current scrollview (here)

How to change position of item in Recycler View

I am working on an Android app which has a recycler view. I have items ordered randomly in the recycler view. I want to move the fifth item of the list to the first position. And move the item previously at the first position to second position. Can anybody help me with this please?
You can use Collections.swap()
Swaps the elements at the specified positions in the specified list. (If the specified positions are equal, invoking this method leaves the list unchanged.)
METHOD
public static void swap(List<?> list,
int i,
int j)
Parameters:
list - The list in which to swap elements.
i - the index of one element to be swapped.
j - the index of the other element to be swapped.
SAMPLE CODE
// first swap the item using Collections.swap() method
Collections.swap(yourList, firstPosition, positionToSwap);
// than notify your adapter about change in list using notifyItemMoved() method
YourAdapter.notifyItemMoved(firstPosition, positionToSwap);
The way RecyclerView works is every time a new item comes on screen it calls your custom RecyclerView.Adapter subclass. Adapter has a reference for the dataset you take data for views from and gets passed the ViewHolder (the layout of an item) and index into onBindViewHolder(MyViewHolder holder, int position) to take dataset[position] and put the data into holder.textview.setText(dataset[position]).
As such, to swap places of elements you have 2 options:
rearrange data in the initial dataset. Chances are it's an ArrayList<> of some kind and you do TEMP=dataset[5];ArrayList.remove(TEMP);ArrayList.insert(TEMP,1); ArrayList will shift everything as required.
if it is important to keep dataset intact, you can rewrite your adapter, so that it keeps a map of { position : dataset_index } and populates items according to that map. That should be trivial.
And then you have to refresh the data with adapter.notifyDataSetChaged();

FirebaseListAdapter, How to update individual list views after populateView

I have implemented a firebase list adapter to load a list of items (List A). My data structure is setup such that within List A, each item also contains a reference id to some information located somewhere else (isNice) in the database. Likewise:
ListA
- ObjA
- title : "hi"
- id : "ObjAid"
isNice
- ObjAid : "true"
I'm currently using another database operation to look up the id in the "isNice" child, passing the "ObjAid", the list position, and then a resultReceiver to get the result back. My problem is, when the resultReceiver get a resultData (the value "true"), I have no idea how modify the data within firebase list at the specific position.
My past experience is to use load my data into my own ArrayList and create a custom adapter for the listView, in that case, I could easily update the populated view as extra information is loaded. I would like to avoid setting up my own ArrayList to store the data for the time being, favoring the simplicity of the FirebaseListAdapter. All tips are appreciated, thx :)
After some trial and error, I've instead gone with the RecyclerView + FirebaseRecyclerViewAdapter approach. Using recycler is better for the long run too, in my use case the list could get to 3K+. Using RecyclerView.findViewHolderForAdapterPosition() I can reference the specific itemView after I get the data from the result receiver likewise:
// Reference the Item's view at the specific position
myViewHolder itemViewHolder = recyclerView.findViewHolderForAdapterPosition(position);
// Reference and set the views and here......

How to use RecyclerView.Adapter notifyItemInserted/Removed in a right way?

For instance, you have an adapter and in onBindViewHolder method you set OnClickListener to some views (and do some actions there depending on view position). You should assign final to position param of method onBindViewHolder so it could be accessible from onClick().
After changing dataset (remove or add item in list) you call onItemInserted or onItemRemoved and this really adds/removes a view in the recyclerview, BUT it does not refresh other viewitems so when you click on a neighbor viewitem it will open a screen or show data with invalid index. To avoid this I basically call notifyDatasetChanged to call onBind to all visible views and remove/add some views.
So how to refresh other views when you call notifyItemInserted/removed or how to work with these methots appropriately?
Assigning the position to a variable in onBindViewHolder will lead to an inconsistent state if items in the dataset are inserted or deleted without calling notifyDataSetChanged.
To use onItemInserted or onItemRemoved the data in the viewholder should remain consistent since it will not be redrawn and onClick would use this invalid position assigned before an item was added or removed.
For this and other use cases the RecyclerView.ViewHolder provides methods to access its position and id:
Use getAdapterPosition() or getItemId() to get valid positions and ids.
Also have a look on the other methods available in RecyclerView.ViewHolder.
So, the way I fix the problem I had is by changing the position into viewHolder.getAdapterPosition()
Cheers!
I advise you to add notifyItemRangeChanged after insert or remove list inside adapter. This work for my project.
Example in remove item :
public void removeItem (int pos) {
simpanList.remove(pos);
notifyItemRemoved(pos);
notifyItemRangeChanged(pos, simpanList.size());//add here, this can refresh position cmiiw
}
For future readers, this is what I do when inserting/removing in recyclerview
For example, my model class is CarsModel
In my adapter
ArrayList<CarsModel> carsModel;
In onBindViewHolder
CardModel model = carsModel.get(position);
When removing data in list using button in holder:
int position = holder.getAdapterPosition();
carsModel.remove(position);
notifyItemRemoved(position);
Then when inserting
carsModel.add(0, model);
notifyItemInserted(0);
or insert in last row
carsModel.add(carsModel.size() - 1 , model);
notifyItemInserted(carsModel.size()-1);

Binding a class to a view/viewgroup in Android?

In Android I have a class contains 2 properties. I've created many objects from it and put them into an ArrayList, then using ArrayAdapter to bind the List to a TableView as you see. Once the list is changed, the view will be updated.
The question is, how can I bind my properties with these 2 TextViews in a table-row (a so-called ViewGroup in Android)...? I've tried to take data from the list into 2 String-array: dates and values, but that's odd...
In the getView() method of your adapter, use setTag(), passing in the object you want to attach. You can then, for example, retrieve the object in onListItemClick() (assuming you're using a ListView) by calling Log logItem = (Log) view.getTag().

Categories

Resources