首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >FastAdapter在从LiveData加载后闪烁,即使数据保持不变

FastAdapter在从LiveData加载后闪烁,即使数据保持不变
EN

Stack Overflow用户
提问于 2018-10-30 18:19:44
回答 3查看 1.5K关注 0票数 2

对于我准备好的问题,一个简单而实用的例子

我的示例应用程序使用okhttp下载一个包含游戏中前30名玩家的JSON数组,并将它们存储到SQLite Room中。在片段中,我观察了相应的LiveData<List<TopEntity>>对象并更新了FastAdapter实例:

代码语言:javascript
复制
public class TopFragment extends Fragment {
    private final ItemAdapter<TopItem> mItemAdapter = new ItemAdapter<>();
    private final FastAdapter<TopItem> mFastAdapter = FastAdapter.with(mItemAdapter);

    private TopViewModel mViewModel;
    private ProgressBar mProgressBar;
    private RecyclerView mRecyclerView;

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container,
                             Bundle savedInstanceState) {

        mViewModel = ViewModelProviders.of(this).get(TopViewModel.class);
        mViewModel.getTops().observe(this, tops -> {
            mItemAdapter.clear();
            for (TopEntity top: tops) {
                TopItem item = new TopItem(top);
                mItemAdapter.add(item);
            }
        });

        View v = inflater.inflate(R.layout.top_fragment, container, false);
        mProgressBar = v.findViewById(R.id.progressBar);
        mRecyclerView = v.findViewById(R.id.recyclerView);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        mRecyclerView.setAdapter(mFastAdapter);

        fetchJsonData();

        return v;
    }

我的问题是:每下载一次数据,回收商的视图就会闪烁一次。

即使前30名不经常变化,也就是数据保持不变。

当我查看彭斯先生的优秀FastAdapter库中的示例应用程序时,我没有看到任何闪现。

更新:

我得到了暗示,很明显,闪烁是由于在onChanged方法中调用mItemAdapter.clear();而引起的,所以我应该使用DiffUtil类。

所以我增加了一个新的类:

代码语言:javascript
复制
public class DiffCallback extends DiffUtil.Callback {
    private final List<TopItem> mOldList;
    private final List<TopItem> mNewList;

    public DiffCallback(List<TopItem> oldStudentList, List<TopItem> newStudentList) {
        this.mOldList = oldStudentList;
        this.mNewList = newStudentList;
    }

    @Override
    public int getOldListSize() {
        return mOldList.size();
    }

    @Override
    public int getNewListSize() {
        return mNewList.size();
    }

    @Override
    public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
        TopItem oldItem = mOldList.get(oldItemPosition);
        TopItem newItem = mNewList.get(newItemPosition);

        return oldItem.uid == newItem.uid;
    }

    @Override
    public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
        TopItem oldItem = mOldList.get(oldItemPosition);
        TopItem newItem = mNewList.get(newItemPosition);

        return oldItem.elo == newItem.elo &&
                oldItem.given.equals(newItem.given) &&
                //oldItem.photo != null && oldItem.photo.equals(newItem.photo) &&
                oldItem.avg_time != null && oldItem.avg_time.equals(newItem.avg_time) &&
                oldItem.avg_score == newItem.avg_score;
    }

    @Nullable
    @Override
    public Object getChangePayload(int oldItemPosition, int newItemPosition) {
        return super.getChangePayload(oldItemPosition, newItemPosition);
    }
}

然后,我尝试在onChanged方法中使用它,而不仅仅是调用mItemAdapter.clear(),但是即使tops有元素,RecyclerView仍然是空的:

代码语言:javascript
复制
mViewModel = ViewModelProviders.of(this).get(TopViewModel.class);
mViewModel.getTops().observe(this, tops -> {
    List<TopItem> oldList = mItemAdapter.getAdapterItems();
    List<TopItem> newList = new ArrayList<>();
    for (TopEntity top: tops) {
        TopItem item = new TopItem(top);
        newList.add(item);
    }

    DiffCallback diffCallback = new DiffCallback(oldList, newList);
    DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);

    mItemAdapter.getAdapterItems().clear();
    mItemAdapter.getAdapterItems().addAll(newList);
    diffResult.dispatchUpdatesTo(mFastAdapter);
});

关于我的问题的简短摘要:

我真正的应用程序使用FastAdapter有几个原因,我正在寻找一种将它与DiffUtil“结合”的方法,以消除在HTTPS上下载并在Room中更新数据时的一次性闪烁现象。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-11-02 12:40:55

在FastAdapter作者的帮助下,我通过在TopItem中显示的TopItem中添加一个标识符,消除了一次闪烁:

代码语言:javascript
复制
@Override
public long getIdentifier() {
    return uid;
}

通过在我的FastAdapterDiffUtil中使用TopFragment

代码语言:javascript
复制
mViewModel = ViewModelProviders.of(this).get(TopViewModel.class);
mViewModel.getTops().observe(this, tops -> {
    List<TopItem> newList = new ArrayList<>();
    for (TopEntity top: tops) {
        TopItem item = new TopItem(top);
        newList.add(item);
    }

    DiffUtil.DiffResult diffResult = FastAdapterDiffUtil.calculateDiff(mItemAdapter, newList);
    FastAdapterDiffUtil.set(mItemAdapter, diffResult);
});
票数 4
EN

Stack Overflow用户

发布于 2018-11-02 12:22:09

避免闪烁的一个简单方法是禁用RecyclerViewItemAnimator

代码语言:javascript
复制
mRecyclerView.setItemAnimator(null);
票数 5
EN

Stack Overflow用户

发布于 2018-11-02 11:21:36

尝试从getChangePayload()方法返回一些标记对象。

代码语言:javascript
复制
@Nullable
@Override
public Object getChangePayload(final int oldItemPosition, final int newItemPosition) {
    return mNewList.get(newItemPosition);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53070525

复制
相关文章

相似问题

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