如何在从服务器提取数据后更新recyclerview?

时间:2016-03-07 23:38:09

标签: android android-recyclerview

如果我必须发送请求以获取onBindViewHolder()内的数据,如何在数据从服务器返回后更新视图?

我现在拥有的是我将数据与行位置一起缓存,以便下次当用户滚动到该行时,我可以立即显示信息。

但还有其他两个问题,我不知道如何解决。

  1. 我滚动列表以查看位置10,11和12的项目。我决定等待数据返回。我之后打电话给notifyDataSetChanged()吗?因为onBindViewHolder已经在数据返回时被调用,并且视图将保持为空,但我也不会想到在每个请求之后调用notifyDataSetChanged()是个好主意。
  2. 我开始查看位置0处的列表并继续滚动到位置10.应用程序发出请求以将位置0的数据拉到10.因为0处的请求首先被发送出去,更可能是先返回或至少比位置10早,但到那时我已经在位置10查看该项目。如果所有请求都按顺序返回,我的视图将开始改变,因此它将显示位置0的数据然后继续更新所有10月的方式。
  3. recyclerview滚动时从服务器加载数据是不好的做法吗?但通过这样做可以节省我很多时间,我想对用户也是如此?因为用户不是提前发送所有请求,而是在后台加载其他数据时看到部分数据。

    感谢!!!

    EDITED

    public class TestAdapter extends RecyclerView.Adapter<TestAdapter.ViewHolder> {
        private Context ctx;
        private ArrayList<Photo> alPhotos = new ArrayList<>();
        private HashMap<String, Drawable> hmImages = new HashMap<>();
    
        public TestAdapter(Context ctx, ArrayList<Photo> alPhotos) {
            this.ctx = ctx;
            this.alPhotos = alPhotos;
        }
    
        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_photo_brief, parent, false));
        }
    
        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            Photo photo = alPhotos.get(position);
    
            loadRemoteImage(photo.IMG, holder.ivThumb, true);
            holder.tvEmail.setText(photo.EMAIL);
        }
    
        @Override
        public int getItemCount() {
            return alPhotos.size();
        }
    
        private void loadRemoteImage(final String imgUrl, final ImageView view, final boolean cache) {
            if (hmImages.containsKey(imgUrl)) {
                view.setImageDrawable(hmImages.get(imgUrl));
            } else {
                final WeakReference<ImageView> weakView = new WeakReference<>(view);
                RequestManager.getManager().add(new Request<>(imgUrl, new DrawableParser(), new RequestCallback<Drawable>() {
                            @Override
                            public void onFinished(Request<Drawable> request, Response<Drawable> response) {
                                if (cache) hmImages.put(imgUrl, response.result);
    
                                ImageView view = weakView.get();
                                if (view != null) {
                                    view.setImageDrawable(response.result);
                                }
                            }
    
                            @Override
                            public void onError(Request<Drawable> request, Response<Drawable> response) {
                            }
    
                            @Override
                            public void onTimeout(Request<Drawable> request, Response<Drawable> response) {
                            }
                        })
                );
            }
        }
    
        public class ViewHolder extends RecyclerView.ViewHolder {
            private ImageView ivThumb;
            private TextView tvEmail;
    
            public ViewHolder(View itemView) {
                super(itemView);
                findViews();
            }
    
            private void findViews() {
                ivThumb = (ImageView) itemView.findViewById(R.id.ivThumb);
                tvEmail = (TextView) itemView.findViewById(R.id.tvEmail);
            }
        }
    }
    

1 个答案:

答案 0 :(得分:3)

在滚动时加载数据是一个好主意,很多流行的应用都会这样做。在这种情况下,我个人使用WeakReference。当我开始加载数据时,我在模型中存储了对视图持有者的弱引用。如果在我得到响应时引用仍然有效,那么更新视图是有意义的。如果内存中没有视图持有者,那么它已被回收,我不再需要更新任何内容。

调用onViewRecycled时,您可以清除弱引用,并考虑取消网络请求(取决于您的需求)。

缓存适用于此模型,您只需在发出网络请求之前插入此逻辑。同样,这取决于您的需求,也许您根本不需要缓存,或者您的数据很少更新,因此在某些事件之前始终使用缓存是有意义的。

在我的应用中,我也使用EventBus,它可以帮助我处理事件,但是使用Android SDK和支持库绝对没问题。

如果您需要根据用户是否立即滚动列表来区分项目行为,也可以添加ScrollListener。例如。在我的应用程序中,如果加载列表并且用户没有滚动它(改善与用户的交互),我会为数据设置动画。当用户滚动时,我按原样加载数据,因为如果我为数据设置动画,它将在屏幕上运动过多。