我的问题是如何在PagedList中更新项目?
在我的例子中,有ListActivity和DetailsActivity。列表活动正在使用分页组件从网络获取帖子(仅限),并使用分页适配器在回收器视图中显示它。当用户按下一些帖子,我需要获得帖子的详细信息,并在DetailsActivity上显示它。我正在向服务器发出另一个请求,它返回给我post详细信息。调用之后,服务器增加该帖子的viewsCount值,当用户返回到帖子列表时,我需要更新列表项中的计数器。
问题是,如何在PagedList中更新单个项目(post),因为我不需要从头开始重新加载所有列表来更新单个项目。
发布于 2018-10-30 13:24:31
PagedList是不可变的
我建议您不要使用分页库,因为它假定您的数据是不可变的,这在实际用例中几乎是不可能的。
您可以在official docs中查看它。上面写着:
如果您有更细粒度的更新信号,例如网络API发出更新列表中单个项目的信号,建议您将数据从网络加载到内存中。然后,通过包装内存快照的DataSource将数据呈现给PagedList。每次内存中的副本发生更改时,都会使以前的DataSource无效,并且可以创建包装快照的新状态的新快照。
即,
您必须从服务器获取数据,然后使用房间库将其存储到本地DB中,然后当您需要更新任何项目时,将项目更新到本地DB中,反过来, room 会将这些更改反映到UI中(使用LiveData)。
但是,您必须使用本地DB进行分页。
在空间的情况下,你会有类似这样的东西。
@Dao
interface FeedDao {
@Query("SELECT * FROM feed ")
fun selectPaged(): DataSource.Factory<Int, Feed>
}但是,你还需要处理更多的事情,比如:
如果从远程服务器上删除了一个实体,该怎么办?我们怎么才能注意到这一点?
我们必须将它从本地DB 中删除。
你可以阅读this的文章来解决这个问题。它解释了分页库中的所有问题,以及如果您真的想要使用分页库时可能的解决方法。
我的建议是使用this库并实现您自己的分页。
发布于 2018-10-24 00:04:36
PagedListAdapter使用的DiffUtil.ItemCallback只会在它认为是“新”项的情况下更新现有项。在我看来,您确实需要到服务器获取新的视图计数,但您也不希望重绘未受影响的项目。这可以通过向DiffUtil.ItemCallback添加视图计数属性来确定新项是什么来防止。具有新视图计数的项目将被重新绘制,而其他项目则不会。
我假设检索第一个列表的原始请求返回的对象中包含viewsCount字段。
发布于 2018-10-29 11:44:40
我已经在recyclerview中实现了分页,你可以在git hub https://github.com/kunal-mahajan/GitRepositoryList上检查这个例子,你不会使用下面的代码一次又一次地重新加载数据。
步骤1:创建类DynamicLoadingAdapter
import android.content.Context;
import android.graphics.Typeface;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public abstract class DynamicLoadingAdapter extends RecyclerView.Adapter<ViewHolder> {
private static final int ITEM = 3;
private static final int LOADING = 4;
private static final int NO_DATA = 5;
protected List records;
protected Context context;
private LoadingObj loadingObj = new LoadingObj();
private NoDataAvailableObj noDataAvailableObj = new NoDataAvailableObj();
public DynamicLoadingAdapter(Context context) {
this.context = context;
records = new ArrayList<>();
records.add(loadingObj);
}
private int getIntToDP(int px) {
return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, px, context.getResources().getDisplayMetrics()));
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ViewHolder viewHolder = null;
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch (viewType) {
case ITEM:
viewHolder = getViewHolder(parent, inflater);
break;
case LOADING:
viewHolder = new DynamicLoadingAdapter.LoadingVH(getProgressBar());
break;
case NO_DATA:
viewHolder = new ViewHolder(getNoDataTextView()) {
};
}
return viewHolder;
}
protected abstract String getEmptyText();
@NonNull
protected abstract ViewHolder getViewHolder(ViewGroup parent, LayoutInflater inflater);
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (getItemViewType(position) == ITEM)
setValuesOnBind(holder, position);
}
protected abstract void setValuesOnBind(ViewHolder holder, int position);
@Override
public int getItemViewType(int position) {
Object o = records.get(position);
if (o instanceof LoadingObj)
return LOADING;
if (o instanceof NoDataAvailableObj)
return NO_DATA;
return ITEM;
}
void setLoadingFinished() {
records.remove(records.size() - 1);
if (records.size() == 0) records.add(new NoDataAvailableObj());
notifyDataSetChanged();
}
@Override
public int getItemCount() {
return records.size();
}
int getItemLoadedCount() {
int l = records.size();
if (records.get(records.size() - 1).equals(loadingObj))
l--;
if (l > 0 && records.get(0).equals(noDataAvailableObj))
l--;
return l;
}
void add(List list) {
for (int i = 0; i < list.size(); i++) {
records.add(records.size() - 1, list.get(i));
}
notifyDataSetChanged();
}
private ProgressBar getProgressBar() {
ProgressBar progressBar = new ProgressBar(context);
int h = getIntToDP(30);
int w = ViewGroup.LayoutParams.MATCH_PARENT;
LinearLayout.LayoutParams progressParams = new LinearLayout.LayoutParams(w, h);
int margin = getIntToDP(5);
progressParams.setMargins(margin, margin, margin, margin);
progressParams.gravity = Gravity.CENTER;
progressBar.setLayoutParams(progressParams);
return progressBar;
}
public TextView getNoDataTextView() {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
TextView textView = new TextView(context);
textView.setGravity(Gravity.CENTER);
textView.setText(getEmptyText());
textView.setTypeface(null, Typeface.ITALIC);
params.setMargins(0, getIntToDP(7), 0, getIntToDP(7));
textView.setLayoutParams(params);
return textView;
}
private static class LoadingObj {
}
private class LoadingVH extends ViewHolder {
public LoadingVH(View itemView) {
super(itemView);
}
}
private class NoDataAvailableObj {
}
}步骤2:创建类: DynamicLoadingListHelper
import android.content.Context;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import java.util.List;
/**
* Created by Kunal.Mahajan on 7/23/2018.
*/
public abstract class DynamicLoadingListHelper {
private final DynamicLoadingAdapter adapter;
private final Context context;
private LinearLayout containerLayout;
private RecyclerView rv;
private int totalRecords = -1;
private int pageCount = 0;
public DynamicLoadingListHelper(Context context, LinearLayout containerLayout, DynamicLoadingAdapter adapter) {
this.adapter = adapter;
this.context = context;
this.containerLayout = containerLayout;
init();
}
public void init() {
final LinearLayoutManager lm = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false);
rv = new RecyclerView(context);
rv.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
containerLayout.addView(rv);
rv.setLayoutManager(lm);
rv.setItemAnimator(new DefaultItemAnimator());
rv.setAdapter(adapter);
rv.addOnScrollListener(new RecyclerView.OnScrollListener() {
int lastLoadCountReq = Integer.MIN_VALUE;
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (lm.findLastVisibleItemPosition() == adapter.getItemCount() - 1 && newState == RecyclerView.SCROLL_STATE_IDLE && adapter.getItemLoadedCount() < totalRecords && adapter.getItemLoadedCount() > lastLoadCountReq) {
lastLoadCountReq = adapter.getItemLoadedCount();
loadNextPage();
}
}
});
rv.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
LinearLayoutManager layoutManager = (LinearLayoutManager) rv.getLayoutManager();
@Override
public void onChildViewAttachedToWindow(View view) {
boolean isScrolled = layoutManager.findViewByPosition(0) != layoutManager.findViewByPosition(layoutManager.findFirstCompletelyVisibleItemPosition());
if (isScrolled)
return;
if (!(view instanceof ProgressBar))
return;
if (isRecyclerScrollable()) {
loadNextPage();
}
}
public void onChildViewDetachedFromWindow(View view) {
}
});
loadNextPage();
}
private void loadNextPage() {
pageCount++;
loadData(pageCount);
}
private boolean isRecyclerScrollable() {
LinearLayoutManager layoutManager = (LinearLayoutManager) rv.getLayoutManager();
RecyclerView.Adapter adapter = rv.getAdapter();
if (layoutManager == null || adapter == null) return false;
return layoutManager.findLastCompletelyVisibleItemPosition() < totalRecords;
}
protected abstract void loadData(int offset);
public void dataLoaded(List list, int totalPage) {
if (totalPage <= 0) {
adapter.setLoadingFinished();
return;
}
this.totalRecords = totalPage;
adapter.add(list);
if (adapter.getItemLoadedCount() >= totalPage)
adapter.setLoadingFinished();
}
}步骤3:创建您自己的PaginationAdaptor,例如:
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.gitfeaturelisting.R;
import com.gitfeaturelisting.component.DynamicLoadingAdapter;
import com.gitfeaturelisting.pojo.Item;
import com.squareup.picasso.Picasso;
/**
* Created by Kunal.Mahajan on 7/23/2018.
*/
public class RepoPaginationAdaptor extends DynamicLoadingAdapter {
public RepoPaginationAdaptor(Context applicationContext) {
super(applicationContext);
}
@Override
protected String getEmptyText() {
return "No repo available";
}
@NonNull
@Override
protected RecyclerView.ViewHolder getViewHolder(ViewGroup parent, LayoutInflater inflater) {
View v = inflater.inflate(R.layout.layout_repo_info_short, parent, false);
final RecyclerView.ViewHolder viewHolder = new RepoInfoVH(v);
return viewHolder;
}
@Override
protected void setValuesOnBind(RecyclerView.ViewHolder holder, int position) {
Item r = (Item) records.get(position);
RepoInfoVH rvh = (RepoInfoVH) holder;
rvh.tvName.setText(r.getDescription());
rvh.tvTitle.setText(r.getName());
rvh.tvRate.setText(context.getString(R.string.updated_on) + " " + (r.getUpdatedAt()));
Picasso.get().load(Uri.parse(r.getOwner().getAvatarUrl())).into(rvh.ivPic);
rvh.llMain.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(context, ActivityRepoDetail.class);
Item r = (Item) records.get(rvh.getLayoutPosition());
i.putExtra(ActivityRepoDetail.KEY_REPO_DETAIL, r);
context.startActivity(i);
}
});
}
private class
RepoInfoVH extends RecyclerView.ViewHolder {
ImageView ivPic;
TextView tvName;
TextView tvTitle;
TextView tvRate;
LinearLayout llMain;
public RepoInfoVH(View jobView) {
super(jobView);
ivPic = jobView.findViewById(R.id.layout_repo_info_short_iv_repo_pic);
tvName = (jobView.findViewById(R.id.layout_repo_info_short_tv_name));
tvTitle = (jobView.findViewById(R.id.layout_repo_info_short_tv_title));
tvRate = (jobView.findViewById(R.id.layout_repo_info_short_tv_bottom));
llMain = (jobView.findViewById(R.id.layout_repo_info_short_ll));
}
}
}https://stackoverflow.com/questions/48255109
复制相似问题