When displaying a list format View on Android, it is mainstream to use RecyclerView. When it was necessary to add / delete / update the contents of the RecyclerView list, it was the mainstream to use the notify method. However, DiffUtils has been added from Supoprt Library 24, and it has become mainstream to use dispatchUpdateTo which calculates the diff of the past list and the new list with DiffUtils and reads the optimal notify method for performance based on the result. I think that there. So let's create a minimum sample to add a list with DiffUtils.
↓ Completed image
If you don't know how to display RecyclerView itself, please refer to the following article. [[For beginners] Minimum sample of RecyclerView in Java](https://qiita.com/kawano108/items/7f92c8088d84d1f60434# Step to display)
Let's look at each one.
Create an instance of the DiffResult class. The initial state is as follows.
DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() {
@Override
public int getOldListSize() {
return 0;
}
@Override
public int getNewListSize() {
return 0;
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return false;
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return false;
}
});
Create a function that receives the list in the Adapter and calls dispatchUpdateTo from DiffResult.
public class MainAdapter extends RecyclerView.Adapter<MainAdapter.MainViewHolder> {
private List<MainActivity.RowData> rowDataList;
MainAdapter(List<MainActivity.RowData> rowDataList) {
this.rowDataList = rowDataList;
}
/**
*Update the list of RecyclerView nicely based on DiffResult
* @param newItems List to update
*/
public void setData(final List<RowData> newItems) {
DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() {
@Override
public int getOldListSize() {
return rowDataList.size();
}
@Override
public int getNewListSize() {
return newItems.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return rowDataList.get(oldItemPosition).hogeTitle.equals(newItems.get(newItemPosition).hogeTitle);
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return rowDataList.get(oldItemPosition).hogeContents.equals(newItems.get(newItemPosition).hogeContents);
}
});
this.rowDataList = newItems;
result.dispatchUpdatesTo(this);
}
/**
*One line of data
*/
static class MainViewHolder extends RecyclerView.ViewHolder {
ImageView hogeImage;
TextView hogeTitle;
TextView hogeContents;
MainViewHolder(@NonNull View itemView) {
super(itemView);
hogeImage = itemView.findViewById(R.id.hoge_image_view);
hogeTitle = itemView.findViewById(R.id.hoge_title_text_view);
hogeContents = itemView.findViewById(R.id.hoge_contents_text_view);
}
}
/**
*ViewHolder method
*Only called first.
*Here, the ViewHolder that generated the ViewHolder layout file as inflation is returned to the RecyclerView.
* @param parent
* @param viewType
* @return
*/
@NonNull
@Override
public MainViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_holder_main, parent, false);
return new MainViewHolder(view);
}
/**
*Bind ViewHolder and RecyclerView
*Write here the processing that you want to do in common for one line of View. This time I only set the text.
* @param holder
* @param position
*/
@Override
public void onBindViewHolder(@NonNull MainViewHolder holder, int position) {
RowData rowData = this.rowDataList.get(position);
holder.hogeTitle.setText(rowData.hogeTitle);
holder.hogeContents.setText(rowData.hogeContents);
}
/**
*Number of rows in the list
* @return
*/
@Override
public int getItemCount() {
return rowDataList.size();
}
}
Now that we have a function for updating in the Adapter, let's call it on the Activity side where RecyclerView is mounted.
public class MainActivity extends AppCompatActivity {
private int page = 1;
@Nullable
private MainAdapter mainAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/**
*RecyclerView setup
*/
RecyclerView recyclerView = findViewById(R.id.main_recycler_view);
//Turn on the setting that does not change the layout size of RecyclerView
//Settings for improving performance.
recyclerView.setHasFixedSize(true);
//Set layoutManager in RecyclerView.
//Depending on the type of this layoutManager, you can select "one-column list" or "two-column list".
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
//Generate Adapter and set it in RecyclerView
this.mainAdapter = new MainAdapter(createRowData(page));
recyclerView.setAdapter(mainAdapter);
/**
*Set the process to add 20 lines with the click of a button
*/
Button button = findViewById(R.id.main_button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
page ++;
mainAdapter.setData(createRowData(page));
}
});
}
private List<RowData> createRowData(@Nullable int page) {
List<RowData> dataSet = new ArrayList<>();
int i = 1;
while (i < page * 20) {
RowData data = new RowData();
data.hogeTitle = "hogeTitle" + Integer.toString(i);
data.hogeContents = "hogeContents" + Integer.toString(i);
dataSet.add(data);
i = i + 1;
}
return dataSet;
}
class RowData {
Image hogeImage;
String hogeTitle;
String hogeContents;
}
}
I will build it when I can do it so far. When you press the button, the number of lines increases by 20.
Recommended Posts