I intialize my recycler view adapter with an empty arraylist initially.
Then later once I fetch data from API I try to update the adapter by calling notifyDataSetChanged() but none of call back methods in my adapter is getting fired
void initRecyclerView()
{
myList = new ArrayList<>();
myRecyclerAdapter = new myRecyclerAdapter(getActivity(), myList, "");
myRecyclerView.setAdapter(myRecyclerAdapter);
linearLayoutManager = new LinearLayoutManager(getActivity());
myRecyclerView.setHasFixedSize(true);
myRecyclerView.setLayoutManager(linearLayoutManager);
}
After getting data from API I just update the adapter as follow :
void updateRecyclerView(ArrayList<Data> newList)
{
if (myList.isEmpty())
linearLayoutManager.removeAllViews();
myList.clear();
myList.addAll(newList);
myRecyclerAdapter.notifyDataSetChanged();
}
void updateRecyclerView(ArrayList<Data> newList)
{
//you don't have to removeviews
// if (myList.isEmpty())
// linearLayoutManager.removeAllViews();
myList.clear();
myList.addAll(newList);
myRecyclerAdapter.notifyDataSetChanged();
}
I made a costliest mistake and ponder around something else instead of looking it at different aspect.
I had SwipeRefreshLayout that wraps RecyclerView.
I should've just use setRefreshing(false) once data downloaded through API call. Instead I used setVisibility(VIEW.GONE) on mymSwipeRefreshLayout`.
This visibility change of SwipeRefreshLayout impacted RecyclerView within.
I hope none will do this mistake. Perhaps someone might come across this tiniest mistake so I Mark my answer as accepted answer.
First of all try to set layout manager and then set adapter to list :
void initRecyclerView()
{
linearLayoutManager = new LinearLayoutManager(getActivity());
myRecyclerView.setHasFixedSize(true);
myRecyclerView.setLayoutManager(linearLayoutManager);
myList = new ArrayList<>();
myRecyclerAdapter = new myRecyclerAdapter(getActivity(), myList, "");
myRecyclerView.setAdapter(myRecyclerAdapter);
}
Also pay attention that if you want to change data set or notify your adapter about the changes, you should do it in your main thread.
runOnUiThread(new Runnable() {
#Override
public void run() {
myList.clear();
myList.addAll(newList);
myRecyclerAdapter.notifyDataSetChanged();
}
});
Related
I'm trying to update my recyclerview using notifyDataSetChanged() but it doesn't work. I am setting the adapter to the recyclerview like this:
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(ctx, LinearLayoutManager.VERTICAL, false);
lstSong.setLayoutManager(mLayoutManager);
lstSong.setItemAnimator(new DefaultItemAnimator());
lstSong.addItemDecoration(new GridSpacingItemDecoration(2, dpToPx(0), true));
arrSong = new ArrayList<Song>();
arrSong = kFunc.getAllSong();
songAdapter = new SongAdapter(ctx, arrSong);
lstSong.setAdapter(songAdapter);
This lines of code displays the data. But when i add a new data and refresh the recyclerview with songAdapter.notifyDataSetChanged(); the data won't show up. I know i can display it by using setAdapter() but i want to do it properly.
I add the data before I make the refresh. This is the code:
kFunc = new Function(ctx);
Song song = new Song();
song.setTitle(title);
song.setArtist(artist);
song.setYear_released(yearReleased);
song.setAlbum(album);
song.setGenre(genre);
song.setDuration(duration);
song.setCode(code);
song.setLyrics(lyrics);
kFunc.addSong(song);
dialog.dismiss();
arrSong = kFunc.getAllSong();
songAdapter.notifyDataSetChanged();
Create a method inside adapter like
public updateItems(ArrayList<Song> songs){
arrSong=songs;
}
And while getting new values in your class call the method using adapdter object
lstSong.updateItems(arrSong);
notifyDataSetChanged();
I don't know where you added new item to RecyclerView.Adapter. This is a sample code to add and set a item. More detail Sample RecyclerViewAdapter
#Override
public void addItem(M item) {
items.add(item);
notifyItemInserted(items.size() - 1);
}
#Override
public void addItem(int position, M item) {
items.add(position, item);
notifyItemInserted(position);
}
#Override
public void addAllItems(List<M> items) {
this.items.addAll(items);
notifyDataSetChanged();
}
#Override
public void setItems(List<M> items) {
this.items = items;
notifyDataSetChanged();
}
You should try by updating the list of the songs before you notify the adapter.
for example
arraySongs = <retrive updated data of the song>;
adapter.notifyDataStateChanged()
if you are in ListView which you are not but for you information only.
adapter.lstSong =<updated songs List>;
adapter.notifyDataStteChanged();
try this this worked for me.
happy coding. :)
I'm adding content to my database (Firebase) which are suppose to be loaded into my recyclerview. But the new content always appear at the bottom of the recyclerview. Is there any way to make them appear at the top rather than appear at the bottom
If you want to appear new Items on the top just Add this code in your Activity.
you need to reverse your RecyclerView, then you totally need this code segment. It does not require any modification or any special library. It’s so simple to work on LinearLayoutManager .
LinearLayoutManager mLayoutManager = new LinearLayoutManager(this);
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(mLayoutManager);
First you need to create a LinearLayoutManager object and use “setReverseLayout(true)” and “setStackFromEnd(true)” methods to reverse and add item at the end.
I finally solved the issue all i needed to do was to initialize an integer variable as 0,add it along side with the object of the model class that is to be gotten from the Firebase database and finally notifying an item inserted to the adapter.The code will explain better
int position = 0;
ArrayList<Places> data = new ArrayList<>();
LinearLayoutManager lg = new LinearLayoutManager(this);
then the final code was this
valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
Places content = ds.getValue(Places.class);
data.add(position,content);
adapter = new YourAdapter(data, getApplicationContext);
recyclerview.setLayoutManager(new Line);
recyclerview.setAdapter(adapter);
adapter.notifyItemInserted(position);
adapter.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Handle error code here
}
});
I'm attempting to get method to handle updates to the ListView when SetWeatherData is called. Nothing ever shows up in my listview below. Any ideas? _rootView points to the right root and ListView comes back not null. m_weatherdata has a couple string elements in it.
Note the initial set of data does not show up either. Just blank.
I'm thinking it should be easier to setup a generic method to update a ListView when the data changes using straight up code.
private ArrayList<String> m_weatherdata;
private void SetWeatherData ( ArrayList<String> _weather)
{
m_weatherdata = _weather;
UpdateWeatherUI();
return;
}
ArrayAdapter<String> m_adapter = null;
private void UpdateWeatherUI()
{
if ( m_adapter == null ) {
m_adapter = new ArrayAdapter<String>(
this.getContext(),
R.layout.list_item_forecast,
R.id.list_item_forecast_textview,
m_weatherdata);
View _rootview = this.getLayoutInflater(null).inflate(R.layout.fragment_main, null, false);
ListView _listview = (ListView) _rootview.findViewById(R.id.listview_forecast);
_listview.setAdapter(m_adapter);
}
else
{
m_adapter.notifyDataSetChanged();
}
}
You are assigning a new ArrayList to your dataset.
m_weatherdata = _weather;
Instead add items to the dataset. Like this
m_weatherdata.addAll(_weather);
private void SetWeatherData ( ArrayList<String> _weather)
{
m_weatherdata.addAll(_weather);//change here
UpdateWeatherUI();
return;
}
When you set an adapter there is an observer attached to the
underlying data. So notifyDatasetChanged() only works if you only
modify the data in it.
If you want to clear all data from your dataset before adding new items to it, use the clear() method of ArrayList
private void SetWeatherData ( ArrayList<String> _weather)
{
m_weatherdata.clear();//change here
m_weatherdata.addAll(_weather);//change here
UpdateWeatherUI();
return;
}
m_weatherdata = _weather; // updates the local variable with new set of data. but adapter doesn't know about the changes made as you have created the instance of the adapter with array list by the following line of code.
m_adapter = new ArrayAdapter<String>(this.getContext(), R.layout.list_item_forecast,R.id.list_item_forecast_textview,m_weatherdata);
In you want to updated the data either call
m_adapter.addAll(newsetofstringtobeadded);
or
Create new adapter
This will update your list.
I am trying to remove all the elements from my RecyclerView in my onRestart method so the items don't get loaded twice:
#Override
protected void onRestart() {
super.onRestart();
// first clear the recycler view so items are not populated twice
for (int i = 0; i < recyclerAdapter.getSize(); i++) {
recyclerAdapter.delete(i);
}
// then reload the data
PostCall doPostCall = new PostCall(); // my AsyncTask...
doPostCall.execute();
}
But for some reason the delete method I created in the adapter is not functioning properly:
in RecyclerAdapter.java:
public void delete(int position){
myList.remove(position);
notifyItemRemoved(position);
}
public int getSize(){
return myList.size();
}
I think every other item in my list gets deleted instead of the entire list.
With a listview it was so easy and I simply called adapter.clear().
Can someone please help me fix up the code?
I think I should be using notifyItemRangeRemoved(...,...); but I am not sure how. TIA
This works great for me:
public void clear() {
int size = data.size();
if (size > 0) {
for (int i = 0; i < size; i++) {
data.remove(0);
}
notifyItemRangeRemoved(0, size);
}
}
Source: https://github.com/mikepenz/LollipopShowcase/blob/master/app/src/main/java/com/mikepenz/lollipopshowcase/adapter/ApplicationAdapter.java
or:
public void clear() {
int size = data.size();
data.clear();
notifyItemRangeRemoved(0, size);
}
For you:
#Override
protected void onRestart() {
super.onRestart();
// first clear the recycler view so items are not populated twice
recyclerAdapter.clear();
// then reload the data
PostCall doPostCall = new PostCall(); // my AsyncTask...
doPostCall.execute();
}
Avoid deleting your items in a for loop and calling notifyDataSetChanged in every iteration. Instead just call the clear method in your list myList.clear(); and then notify your adapter
public void clearData() {
myList.clear(); // clear list
mAdapter.notifyDataSetChanged(); // let your adapter know about the changes and reload view.
}
setAdapter(null);
Useful if RecycleView have different views type
recyclerView.removeAllViewsInLayout();
The above line would help you remove all views from the layout.
For you:
#Override
protected void onRestart() {
super.onRestart();
recyclerView.removeAllViewsInLayout(); //removes all the views
//then reload the data
PostCall doPostCall = new PostCall(); //my AsyncTask...
doPostCall.execute();
}
This is how I cleared my recyclerview and added new items to it with animation:
mList.clear();
mAdapter.notifyDataSetChanged();
mSwipeRefreshLayout.setRefreshing(false);
//reset adapter with empty array list (it did the trick animation)
mAdapter = new MyAdapter(context, mList);
recyclerView.setAdapter(mAdapter);
mList.addAll(newList);
mAdapter.notifyDataSetChanged();
Help yourself:
public void clearAdapter() {
arrayNull.clear();
notifyDataSetChanged();
}
I use this. This actually clears the recylerview completely. I had tried adapter.notifyDataSetChanged(); but it was just not updating any view in my case. Of course U had cleared the list first. But below code works fine and clears view of recyclerview completely.
listName.clear(); // clear list
adapter = new ModelAdaptor(Activity.this, listName);
recyclerView.setAdapter(adapter);
Another way to clear the recycleview items is to instanciate a new empty adapter.
mRecyclerView.setAdapter(new MyAdapter(this, new ArrayList<MyDataSet>()));
It's probably not the most optimized solution but it's working like a charm.
ListView uses clear().
But, if you're just doing it for RecyclerView. First you have to clear your RecyclerView.Adapter with notifyItemRangeRemoved(0,size)
Then, only you recyclerView.removeAllViewsInLayout().
For my case adding an empty list did the job.
List<Object> data = new ArrayList<>();
adapter.setData(data);
adapter.notifyDataSetChanged();
private void clearRecyclerView() {
CustomListViewValuesArr.clear();
customRecyclerViewAdapter.notifyDataSetChanged();
}
use this func
On Xamarin.Android, It works for me and need change layout
var layout = recyclerView.GetLayoutManager() as GridLayoutManager;
layout.SpanCount = GetItemPerRow(Context);
recyclerView.SetAdapter(null);
recyclerView.SetAdapter(adapter); //reset
You have better clear the array-list that you used for recyleview adapter.
arraylist.clear();
public void clearData() {
mylist.removeAll(mylist);
mAdapter.notifyDataSetChanged();
recyclerView.setAdapter(mAdapter);
}
I am using a listview with section headers as in this example.
http://eshyu.wordpress.com/2010/08/15/cursoradapter-with-alphabet-indexed-section-headers/
The problem is if I delete or add an item, the sections are all wrong. The sections seem to be set up in the constructor of the Adapter so there seems to be no way of refreshing the sections without creating a new adapter. Is there any way to recreate the section headers correctly without creating a new adapter
Thanks
You don't have to create a new adapter to update your ListView's contents. Simply store your Adapter in a field and update your list with the following code:
mAdapter.setList(yourNewList);
mAdapter.notifyDataSetChanged();
To clarify that, your Activity should look like that:
private YourAdapter mAdapter;
protected void onCreate(...) {
...
mAdapter = new YourAdapter(this);
setListAdapter(mAdapter);
updateData();
}
private void updateData() {
List<Data> newData = getYourNewData();
mAdapter.setList(yourNewList);
mAdapter.notifyDataSetChanged();
}