RecyclerView 异步加载 乱序 问题的解决

Posted Mars-xq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RecyclerView 异步加载 乱序 问题的解决相关的知识,希望对你有一定的参考价值。

参考:

郭霖 : Android ListView异步加载图片乱序问题,原因分析及解决方案

方法一:

1、 onCreateViewHolder 中获取 RecyclerView

@Override
public TestHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    View view = inflater.inflate(R.layout.layout_item, parent, false);
    Log.e(TAG, "onCreateViewHolder: parent.getClass=====>" + parent.getClass());
    if (parent instanceof RecyclerView) {
        mRecyclerView = ((RecyclerView) parent); //核心
    }
    TestHolder holder = new TestHolder(view);
    return holder;
}

2、onBindViewHolder中 :itemView子控件 setTag

holder.tvTitle.setTag(key);

3、onBindViewHolder中异步结果的地方 : mRecyclerView.findViewWithTag 找到对应控件再设置值

holder.tvTitle.postDelayed(new Runnable() {
    @Override
    public void run() {
        if (mRecyclerView == null) {
            return;
        }
        //异步获取的值
        String value = finalI + " > " + (finalPosition * 100);
        addValueToMemoryCache(key, value);
        TextView view = (TextView) mRecyclerView.findViewWithTag(key); // 核心
        if (view != null && !TextUtils.isEmpty(value)) {
            view.setText(value);
            view.setVisibility(View.VISIBLE);
        }
    }
}, i);

方法二:

1、RecyclerView.Adapter实现类中定义方法和变量:

private HashMap<String, String> mHashMap = new HashMap<>();

/**
 * 從缓存中获取已存在的值
 *
 * @param key
 * @return
 */
private String getValueFromMemoryCache(String key) {
    return mHashMap.get(key);
}

/**
 * 添加到缓存中
 *
 * @param key
 * @param value
 */
private void addValueToMemoryCache(String key, String value) {
    if (getValueFromMemoryCache(key) == null) {
        mHashMap.put(key, value);
    }
}

2、onBindViewHolder 方法中getValueFromMemoryCache有值直接设置,没值再异步获取,异步获取后addValueToMemoryCache

String memoryValue = getValueFromMemoryCache(key);
if (!TextUtils.isEmpty(memoryValue)) {
    holder.tvTitle.setText(memoryValue);
    holder.tvTitle.setVisibility(View.VISIBLE);
} else if (position % 2 == 0) {
    holder.tvTitle.setVisibility(View.GONE);
} else {
    holder.tvTitle.postDelayed(new Runnable() {
        @Override
        public void run() {
            if (mRecyclerView == null) {
                return;
            }
            //异步获取的值
            String value = finalI + " > " + (finalPosition * 100);
            addValueToMemoryCache(key, value);
            TextView view = (TextView) mRecyclerView.findViewWithTag(key);
            if (view != null && !TextUtils.isEmpty(value)) {
                view.setText(value);
                view.setVisibility(View.VISIBLE);
            }
        }
    }, i);
}

demo:

import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.xq.divider.R;

import java.util.HashMap;
import java.util.List;
import java.util.Random;


public class TestAdapter extends RecyclerView.Adapter<TestAdapter.TestHolder> {

    private List<String> data;
    private static final String TAG = TestAdapter.class.getSimpleName();
    private HashMap<String, String> mHashMap = new HashMap<>();
    private RecyclerView mRecyclerView;

    public TestAdapter(List<String> data) {
        this.data = data;
    }

    public void setData(List<String> data) {
        this.data = data;
        notifyDataSetChanged();
    }

    @Override
    public TestHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View view = inflater.inflate(R.layout.layout_item, parent, false);
        Log.e(TAG, "onCreateViewHolder: parent.getClass=====>" + parent.getClass());
        if (parent instanceof RecyclerView) {
            mRecyclerView = ((RecyclerView) parent);
        }
        TestHolder holder = new TestHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(final TestHolder holder, final int position) {
        if (data != null && data.size() > 0) {
            final String key = data.get(position);

            Random random = new Random();
            int i = random.nextInt(5 * 1000);

            holder.tvContent.setText(key);
            holder.tvTitle.setText("");

            final int finalPosition = position;
            final int finalI = i;

            holder.tvTitle.setTag(key);
            String memoryValue = getValueFromMemoryCache(key);
            if (!TextUtils.isEmpty(memoryValue)) {
                holder.tvTitle.setText(memoryValue);
                holder.tvTitle.setVisibility(View.VISIBLE);
            } else if (position % 2 == 0) {
                holder.tvTitle.setVisibility(View.GONE);
            } else {
                holder.tvTitle.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (mRecyclerView == null) {
                            return;
                        }
                        //异步获取的值
                        String value = finalI + " > " + (finalPosition * 100);
                        addValueToMemoryCache(key, value);
                        TextView view = (TextView) mRecyclerView.findViewWithTag(key);
                        if (view != null && !TextUtils.isEmpty(value)) {
                            view.setText(value);
                            view.setVisibility(View.VISIBLE);
                        }
                    }
                }, i);
            }
        }
    }


    @Override
    public int getItemCount() {
        return data == null ? 0 : data.size();
    }

    static class TestHolder extends RecyclerView.ViewHolder {
        public TextView tvContent;
        public TextView tvTitle;

        public TestHolder(View itemView) {
            super(itemView);
            tvContent = (TextView) itemView.findViewById(R.id.tv_content);
            tvTitle = (TextView) itemView.findViewById(R.id.tv_title);
            tvContent.setTextSize(20.0f);
            tvTitle.setTextSize(16.0f);
        }
    }


    /**
     * 從缓存中获取已存在的值
     *
     * @param key
     * @return
     */
    private String getValueFromMemoryCache(String key) {
        return mHashMap.get(key);
    }

    /**
     * 添加到缓存中
     *
     * @param key
     * @param value
     */
    private void addValueToMemoryCache(String key, String value) {
        if (getValueFromMemoryCache(key) == null) {
            mHashMap.put(key, value);
        }
    }
}

以上是关于RecyclerView 异步加载 乱序 问题的解决的主要内容,如果未能解决你的问题,请参考以下文章

加载数据后 Recyclerview 项目高度更改

基于Android官方AsyncListUtil优化改进RecyclerView分页加载机制

SQLite 的 Recyclerview 第一次显示空白页面

滚动 RecyclerView 时出现“打开的文件太多”

如何让 RecyclerView 更新其布局?

一个RecyclerView的卡顿问题的解决