英文:
How to update specific item range in recyclerview adapter
问题
我有一个recyclerView
。我从服务器获取一个列表,并在我的列表中显示出来。我有分页功能,当我滚动到底部时,我会请求服务器获取接下来的50个项目。唯一的问题是,当我收到响应时,我正在使用notifyDataSetChanged()
来更新整个适配器。
mViewModel.getList().observe(
getViewLifecycleOwner(),
listResult -> {
recycler.getAdapter().notifyDataSetChanged();
});
很简单,我正在使用ViewModel
。当我的观察者发出通知时,我调用notifyDataSetChanged()
。我的适配器从ViewModel
获取列表。当我从服务器获取下一个50个项目时,我只是将新项目添加到现有列表中。在调用notifyDataSetChanged()
之后,适配器会使用这50个新项目更新整个列表。那么,我如何只更新从服务器获取的最后50个项目呢?当我将这些项目添加到列表中时,我需要通知适配器更新其数据。在那里,我找到了notifyItemInserted();
,但它需要位置。
英文:
I have a recyclerView
. I'm fetching a list from server and show it in my list. I have pagination
and when I scroll to bottom, I request the server
to get next e.g. 50 items. The only problem is, when I get the response, I'm updating the whole adapter, using notifyDataSetChanged()
.
mViewModel.getList().observe(
getViewLifecycleOwner(),
listResult -> {
recycler.getAdapter().notifyDataSetChanged();
});
That's simple, I'm using ViewModel
. When my observer notifies, I call notifyDataSetChanged()
. My adapter gets the list from ViewModel
. And when I'm getting next 50 items from server, I just add the new items to an existing list. And after calling notifyDataSetChanged()
adapter updates the whole list with this new 50 items. So how can I update only the last 50 items, that I get from server? When I add this items into list, I need to notify adapter to update its data. There I found one notifyItemInserted();
, but it needs position.
答案1
得分: 1
你可以使用DiffUtils和AsyncListDiffer来完成这项工作(我告诉你这个,但我并没有完全理解它的内部工作原理)。它可以使绘制变得简单,并由Android系统处理。我在一些帖子中读到并了解到,AsyncListDiffer会检查新项目,并且只绘制那些新项目。
以下是一些代码来帮助你:
适配器类
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.AsyncListDiffer;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.SortedSet;
import neilsayok.github.launchertest5.R;
import neilsayok.github.launchertest5.adapter.viewholder.AppDrawerItemVH;
import neilsayok.github.launchertest5.data.AppInfo;
public class AppDrawerRVAdapter extends RecyclerView.Adapter<AppDrawerItemVH> {
private Context context;
private AsyncListDiffer<AppInfo> appList;
public AppDrawerRVAdapter(Context context) {
this.context = context;
appList = new AsyncListDiffer<>(this, new DiffUtil.ItemCallback<AppInfo>() {
@Override
public boolean areItemsTheSame(@NonNull AppInfo oldItem, @NonNull AppInfo newItem) {
return TextUtils.equals(oldItem.getPackageName(), newItem.getPackageName());
}
@Override
public boolean areContentsTheSame(@NonNull AppInfo oldItem, @NonNull AppInfo newItem) {
return TextUtils.equals(newItem.getLable(), oldItem.getLable());
}
});
}
public void submitList(SortedSet<AppInfo> data) {
appList.submitList(new ArrayList<>(data));
}
@NonNull
@Override
public AppDrawerItemVH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new AppDrawerItemVH(LayoutInflater.from(context).inflate(R.layout.app_drawer_item, parent, false));
}
@Override
public void onBindViewHolder(@NonNull AppDrawerItemVH holder, int position) {
final AppInfo app = appList.getCurrentList().get(position);
holder.getAppIcon().setImageDrawable(app.getAppIcon());
holder.getAppLable().setText(app.getLable());
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(app.getPackageName());
context.startActivity(launchIntent);
}
});
}
@Override
public int getItemCount() {
if (appList == null)
return 0;
else
return appList.getCurrentList().size();
}
}
AppInfo类 (这是我用来参考的POJO类)
import android.graphics.drawable.Drawable;
public class AppInfo {
private String lable;
private String packageName;
private Drawable appIcon;
public AppInfo() {
}
public AppInfo(String lable, String packageName, Drawable appIcon) {
this.lable = lable;
this.packageName = packageName;
this.appIcon = appIcon;
}
public String getLable() {
return lable;
}
public void setLable(String lable) {
this.lable = lable;
}
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public Drawable getAppIcon() {
return appIcon;
}
public void setAppIcon(Drawable appIcon) {
this.appIcon = appIcon;
}
}
在您的ViewModel观察者中更改此行代码:
recycler.getAdapter().notifyDataSetChanged();
更改为 appDrawerRVAdapter.submitList(appInfos);
其中_appDrawerRVAdapter_ 是适配器对象。
使用这种方法,您将不再需要调用 notifydatachanged()
或类似的方法。这个链接对我帮助很大。
英文:
You can use DiffUtils With AsyncListDiffer to do the work(I am telling you this but I do not properly understand how it works internally). It makes the drawing easy and handled by the Android System. I have read and found on some posts that AsyncListDiffer checks for new Items and only draw the items that are new.
Here is some codes to help you:
Adapter Class
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.AsyncListDiffer;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.SortedSet;
import neilsayok.github.launchertest5.R;
import neilsayok.github.launchertest5.adapter.viewholder.AppDrawerItemVH;
import neilsayok.github.launchertest5.data.AppInfo;
public class AppDrawerRVAdapter extends RecyclerView.Adapter<AppDrawerItemVH> {
private Context context;
private AsyncListDiffer<AppInfo> appList;
public AppDrawerRVAdapter(Context context) {
this.context = context;
appList = new AsyncListDiffer<>(this, new DiffUtil.ItemCallback<AppInfo>() {
@Override
public boolean areItemsTheSame(@NonNull AppInfo oldItem, @NonNull AppInfo newItem) {
return TextUtils.equals(oldItem.getPackageName(), newItem.getPackageName());
}
@Override
public boolean areContentsTheSame(@NonNull AppInfo oldItem, @NonNull AppInfo newItem) {
return TextUtils.equals(newItem.getLable(), oldItem.getLable());
}
});
}
public void submitList(SortedSet<AppInfo> data) {
appList.submitList(new ArrayList<AppInfo>(data));
}
@NonNull
@Override
public AppDrawerItemVH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new AppDrawerItemVH(LayoutInflater.from(context).inflate(R.layout.app_drawer_item,
parent, false));
}
@Override
public void onBindViewHolder(@NonNull AppDrawerItemVH holder, int position) {
final AppInfo app = appList.getCurrentList().get(position);
holder.getAppIcon().setImageDrawable(app.getAppIcon());
holder.getAppLable().setText(app.getLable());
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(app.getPackageName());
context.startActivity(launchIntent);
}
});
}
@Override
public int getItemCount() {
if (appList == null)
return 0;
else
return appList.getCurrentList().size(); }
}
AppInfo Class (This is my POJO class just given for reference)
import android.graphics.drawable.Drawable;
public class AppInfo {
private String lable;
private String packageName;
private Drawable appIcon;
public AppInfo() {
}
public AppInfo(String lable, String packageName, Drawable appIcon) {
this.lable = lable;
this.packageName = packageName;
this.appIcon = appIcon;
}
public String getLable() {
return lable;
}
public void setLable(String lable) {
this.lable = lable;
}
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public Drawable getAppIcon() {
return appIcon;
}
public void setAppIcon(Drawable appIcon) {
this.appIcon = appIcon;
}
}
Change this line in your ViewModel Observer:
recycler.getAdapter().notifyDataSetChanged();
to appDrawerRVAdapter.submitList(appInfos);
where appDrawerRVAdapter is the adapter object.
With this method you will not have to call notifydatachanged()
or something like that too.This Link helped me a lot.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论