首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >安卓PagedList更新

安卓PagedList更新
EN

Stack Overflow用户
提问于 2018-01-15 07:12:19
回答 4查看 7.2K关注 0票数 14

我的问题是如何在PagedList中更新项目?

在我的例子中,有ListActivity和DetailsActivity。列表活动正在使用分页组件从网络获取帖子(仅限),并使用分页适配器在回收器视图中显示它。当用户按下一些帖子,我需要获得帖子的详细信息,并在DetailsActivity上显示它。我正在向服务器发出另一个请求,它返回给我post详细信息。调用之后,服务器增加该帖子的viewsCount值,当用户返回到帖子列表时,我需要更新列表项中的计数器。

问题是,如何在PagedList中更新单个项目(post),因为我不需要从头开始重新加载所有列表来更新单个项目。

EN

回答 4

Stack Overflow用户

发布于 2018-10-30 13:24:31

PagedList是不可变的

我建议您不要使用分页库,因为它假定您的数据是不可变的,这在实际用例中几乎是不可能的。

您可以在official docs中查看它。上面写着:

如果您有更细粒度的更新信号,例如网络API发出更新列表中单个项目的信号,建议您将数据从网络加载到内存中。然后,通过包装内存快照的DataSource将数据呈现给PagedList。每次内存中的副本发生更改时,都会使以前的DataSource无效,并且可以创建包装快照的新状态的新快照。

即,

您必须从服务器获取数据,然后使用房间库将其存储到本地DB中,然后当您需要更新任何项目时,将项目更新到本地DB中,反过来, room 会将这些更改反映到UI中(使用LiveData)。

但是,您必须使用本地DB进行分页。

在空间的情况下,你会有类似这样的东西。

代码语言:javascript
复制
@Dao
interface FeedDao {
@Query("SELECT * FROM feed ")
fun selectPaged(): DataSource.Factory<Int, Feed>
}

但是,你还需要处理更多的事情,比如:

如果从远程服务器上删除了一个实体,该怎么办?我们怎么才能注意到这一点?

我们必须将它从本地DB 中删除。

你可以阅读this的文章来解决这个问题。它解释了分页库中的所有问题,以及如果您真的想要使用分页库时可能的解决方法。

我的建议是使用this库并实现您自己的分页。

票数 24
EN

Stack Overflow用户

发布于 2018-10-24 00:04:36

PagedListAdapter使用的DiffUtil.ItemCallback只会在它认为是“新”项的情况下更新现有项。在我看来,您确实需要到服务器获取新的视图计数,但您也不希望重绘未受影响的项目。这可以通过向DiffUtil.ItemCallback添加视图计数属性来确定新项是什么来防止。具有新视图计数的项目将被重新绘制,而其他项目则不会。

我假设检索第一个列表的原始请求返回的对象中包含viewsCount字段。

票数 2
EN

Stack Overflow用户

发布于 2018-10-29 11:44:40

我已经在recyclerview中实现了分页,你可以在git hub https://github.com/kunal-mahajan/GitRepositoryList上检查这个例子,你不会使用下面的代码一次又一次地重新加载数据。

步骤1:创建类DynamicLoadingAdapter

代码语言:javascript
复制
    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

代码语言:javascript
复制
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,例如:

代码语言:javascript
复制
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));
        }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48255109

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档