'Why my RecyclerView updated while I don't notify the adapter?
I have some trouble to understand why my recyclerView get update while I add the data only after setAdapter() and never call notifyDataSetChanged() !
In the same type: -> I add 3 String to my list -> Notify the adapter only for the first added (notifyItemInserted)
Result: 3 String displayed.
If anyone can help me understand I will be very grateful to him :)
https://www.noelshack.com/2018-04-5-1516969446-recycler.png
my code:
public class MainActivity extends AppCompatActivity {
List<String> mList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Call before set adapter so it's normal if show when the adapter is set
mList.add("Before set the adapter");
RecyclerView recyclerView = findViewById(R.id.rcv);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
final Adapter mAdapter = new Adapter(mList);
recyclerView.setAdapter(mAdapter);
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mList.add("Button add " +0);
mAdapter.notifyItemInserted(mList.size()-1);
//Again it's showing but never notify
mList.add("Button add " +1);
mList.add("Button add " +2);
}
});
//Called after setAdapter and NEVER notify the adapter but it's still show the data
addMoreData();
}
private void addMoreData() {
for (int i = 0; i < 10; i++) {
mList.add("addMoreData: " + i);
}
}
class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
class ViewHolder extends RecyclerView.ViewHolder {
TextView nameTextView;
ViewHolder(View itemView) {
super(itemView);
nameTextView = (TextView) itemView.findViewById(R.id.textview);
}
}
@Override
public Adapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.raw, parent, false);
return new Adapter.ViewHolder(view);
}
private List<String> mList;
Adapter(List<String> list) {
mList = list;
}
@Override
public void onBindViewHolder(Adapter.ViewHolder holder, int position) {
holder.nameTextView.setText(mList.get(position));
}
@Override
public int getItemCount() {
return mList.size();
}
}
}
Solution 1:[1]
I think, because of notifyDataSetChanged
's working principle, this is the result.
A Google engineer said ;
When you call notifyDataSetChanged, RecyclerView invalidates the data but does not update the UI until the next animation frame. This is how android view system works. When a widget is invalidated (e.g. changing its data) it requests a layout which means it will be re-measured and re-laid out in the next view traversal. This is done so that we can batch all changes until the next time screen will be updated.
That means; nofiyDataSetChanged
waits the UI Thread. So, doesn't matter the below lines of the notifyItemInserted
from your code.
mList.add("Button add " +0);
mAdapter.notifyItemInserted(mList.size()-1);
//Again it's showing but never notify
mList.add("Button add " +1);
mList.add("Button add " +2);
Solution 2:[2]
We mostly use adapter notify calls to keep views that are currently shown in their proper state, it does not prevent adapter from serving the data to RecyclerView component.
You can see it very clearly, if your RecyclerView has scroll - update the list data without notifying it and then scroll to the bottom you will get your new items laid out.
In your case you add item on the end and notify only for it - but LayoutManager determines it can still lay out more views so it does.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | ziLk |
Solution 2 | Mohamed Mohaideen AH |