PagedListAdapter对无效数据不使用DiffUtil

时间:2019-09-19 17:57:38

标签: android android-adapter pagedlist

每次我调用无效数据时,都不会使用DIFF_UTIL。日志未显示,并且整个列表已更新为新数据,从而导致屏幕移动了位置等。不确定此处的问题是什么。

我有PagedListAdapterLiveData<PagedList<Post>> postList,并且我叫postList.getValue().getDataSource().invalidate();来刷新数据。

我有DIFF_UTIL

 public static DiffUtil.ItemCallback<Post> DIFF_CALLBACK =
            new DiffUtil.ItemCallback<Post>() {

                @Override
                public boolean areItemsTheSame(Post oldItem, Post newItem) {
                    Log.d(TAG, "areItemsTheSame with result: "
                            + (oldItem.getId() == newItem.getId()));
                    Log.d(TAG, "areItemsTheSame Old Item is: " + oldItem.toString());
                    Log.d(TAG, "areItemsTheSame New Item is: " + newItem.toString());
                    return oldItem.getId() == newItem.getId();
                }

                @Override
                public boolean areContentsTheSame(Post oldItem, Post newItem) {
                    Log.d(TAG, "areContentsTheSame with result: " + oldItem.equals(newItem));
                    Log.d(TAG, "areContentsTheSame Old Item is: " + oldItem.toString());
                    Log.d(TAG, "areContentsTheSame New Item is: " + newItem.toString());
                    return oldItem.equals(newItem);
                }
            };

我有我的适配器:

import...

public class PostAdapter extends PagedListAdapter<Post, PostAdapter.PostViewHolder> {
    interface...

    protected PostAdapter() {
        super(DIFF_CALLBACK);
    }

    @NonNull
    @Override
    public PostViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater
                .from(parent.getContext()).inflate(R.layout.feed_card_view, parent, false);
        return new PostViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull PostViewHolder holder, int position) {
        Post post = getItem(position);
        Log.d(TAG, "onBindViewHolder with position: " + position);
        if (post != null) {
            setUpPost(holder, post);
            Log.d(TAG, "onBindViewHolder with post: " + post.toString());
        } else {
            holder.clear();
            Log.d(TAG, "onBindViewHolder post is null");
        }
    }

    private void setUpPost(@NonNull PostViewHolder holder, @NonNull Post post) {
       ...do some things to set up post
    }

    class PostViewHolder extends RecyclerView.ViewHolder {
       Buttons etc..

        public PostViewHolder(View itemView) {
            super(itemView);
            button b = findviewbyid...
        }

        void clear() {
            button.invalidate()..
        }
    }
}

我的片段

 @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View v = inflater.inflate(R.layout.fragment_feed, container, false);
        feedViewModel = ViewModelProviders.of(getActivity()).get(FeedViewModel.class);

        RecyclerView recyclerView = v.findViewById(R.id.post_list);
        PostAdapter adapter = new PostAdapter(this);

        feedViewModel.postList.observe(this, pagedList -> {
            try {
                //refresh current list
                adapter.submitList(pagedList);
            } catch (Exception e) {}
        });


        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this.getActivity()));

        return v;
    }

我的ViewModel

public class FeedViewModel extends AndroidViewModel {
    private LiveData<PagedList<Post>> postList;
    private FeedRepository feedRepository;

    public FeedViewModel(final Application application) {
        super(application);
        feedRepository = new FeedRepository();
        postList = feedRepository.getPosts();
    }

    public void refreshPosts() {
        feedRepository.refreshPosts();
    }

    ... 

    public LiveData<PagedList<Post>> getPostList() {
        return postList;
    }
}

存储库

public class FeedRepository {
    private LiveData<PagedList<Post>> postList;

    private static final String TAG = FeedRepository.class.getName();
    private static final int NUMBER_OF_POSTS_TO_GET = 2;
    private static final boolean ENABLE_POST_PAGE_HOLDER = true;
    private static final int NUMBER_OF_POSTS_TO_GET_IN_ADVANCE = 50;
    private static final int NUMBER_OF_POSTS_ON_FIRST_LOAD = 20;

    public FeedRepository() {
        //Prefs on PagedList
        PagedList.Config myPagingConfig = new PagedList.Config.Builder()
                .setPageSize(NUMBER_OF_POSTS_TO_GET)
                .setEnablePlaceholders(ENABLE_POST_PAGE_HOLDER)
                .setPrefetchDistance(NUMBER_OF_POSTS_TO_GET_IN_ADVANCE)
                .setInitialLoadSizeHint(NUMBER_OF_POSTS_ON_FIRST_LOAD)
                .build();

        PostDataSourceFactory postDataSourceFactory = new PostDataSourceFactory();

        postList = new LivePagedListBuilder(
                postDataSourceFactory, myPagingConfig).build();
    }

    public LiveData<PagedList<Post>> getPosts() {
        return postList;
    }

    public void refreshPosts() {
        Log.d(TAG, "refreshPosts, invalidateDataSources()");
        postList.getValue().getDataSource().invalidate();
    }
}

DataSource.Factory

public class PostDataSourceFactory extends DataSource.Factory<String, Post> {
   public PostDataSourceFactory() {
    }

    @NonNull
    @Override
    public DataSource<String, Post> create() {
        PostDataSource postDataSource = new PostDataSource();
        return postDataSource;
    }
}

我在这里遵循google示例:https://developer.android.com/reference/android/arch/paging/PagedListAdapter.html

3 个答案:

答案 0 :(得分:0)

您可以在Ctrl + Click函数上submitList,并查看内核的内部功能。

public void submitList(final List<T> newList) {
    if (newList == mList) {
        // nothing to do if the newList & old List have the same address in memory 
        return;
    }
....
}

因此,尝试提交新的列表数据并重新检查

submitList(new ArrayList<>(list))

有关更多信息,您可以查看完整答案at this post

答案 1 :(得分:0)

尝试覆盖submitList中的Adapter

  override fun submitList(list: List<Model>?) {
        val arrayList: ArrayList<Model>?
        if (list != null) {
            arrayList = ArrayList(list)
        } else {
            arrayList = list
        }
        super.submitList(arrayList)
    }

或更优雅的方式

  override fun submitList(list: List<Model>?) {
        super.submitList(if (list != null) ArrayList(list) else null)
    }

答案 2 :(得分:0)

对于其他任何对“ DiffUtil.ItemCallback <*>()”部分有疑问的人,我也遇到了同样的问题。

每次我要刷新数据时,我都会在“ DataSource”对象上调用invalidate(),具体取决于您要继承的数据源的类型,但是有两个回调“ areItemsTheSame()”和“ areContentsTheSame” ()”没有被触发。

所以我遇到了以下链接:How to stop blinking on recycler view with architecture components paging library

对我来说,窍门是使用“ AsyncPagedListDiffer”以及提交“ pagedList”时。下面的代码在Kotlin中。

fun submitList(pagedList: PagedList<*?>) {
  pagedList.addWeakCallback(pagedList.snapshot(), object : PagedList.Callback() {
    override fun onChanged(position: Int, count: Int) {
    }

    override fun onInserted(position: Int, count: Int) {
      mDiffer.submitList(pagedList)
    }

    override fun onRemoved(position: Int, count: Int) {
    }

  })
}

通过添加这些内容,我的diff回调开始起作用