Android:使用PagedList时如何添加项目和刷新列表? [英] Android: how to add items and refresh list when using PagedList?

查看:135
本文介绍了Android:使用PagedList时如何添加项目和刷新列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已使用PagedList加载项目页面并将其显示在RecyclerView中,并且它成功显示了数字列表(0,1,2,3 ....,99),该列表始终可以向上滚动下来没有任何问题。
当我尝试单击一个按钮来调用appendItems()追加新数据时,它仍然可以使用。但是,当我滚动列表时,应用程序崩溃了。

I've used PagedList for loading page of items and display them in RecyclerView, and it is successfully displaying list of numbers(0,1,2,3....,99), the list can always be scroll up and down without any problem. When I tried to click a button to call appendItems() to append new data, its still fine. However, the app crashed when I scroll the list.

java.util.ConcurrentModificationException
    at java.util.AbstractList$SubAbstractList.size(AbstractList.java:360)
    at androidx.paging.PagedStorage.get(PagedStorage.java:153)
    at androidx.paging.PagedList.get(PagedList.java:384)
    at androidx.paging.AsyncPagedListDiffer.getItem(AsyncPagedListDiffer.java:206)
    at androidx.paging.PagedListAdapter.getItem(PagedListAdapter.java:156)
    at com.mysample.pagedlist.MyPagedListAdapter.onBindViewHolder(MyPagedListAdapter.java:38)
    at com.mysample.pagedlist.MyPagedListAdapter.onBindViewHolder(MyPagedListAdapter.java:19)

似乎我不知道正确的方法来添加更多数据并刷新显示。有人可以告诉我如何解决吗?

It seems I don't know the right way to append more data and refresh the display. Can anyone tell me how to work it out?

Api用作数据库和dao

Api is served as database and dao

public class Api {
    private static List<String> list = null;

    private static void initListIfNeeded() {
        if (list == null) {
            list = new ArrayList<>();
            for (int i = 0; i < 100; i++) {
                list.add("" + i);
            }
        }
    }

    public static List<String> pageItems(int page, int pageSize) {
        initListIfNeeded();
        int start = page * pageSize;
        int end = (page + 1) * pageSize;
        if (end > list.size()) {
            end = list.size();
        }
        if (page < 0 || start >= list.size()) {
            return new ArrayList<>();
        } else {
            return list.subList(start, end);
        }
    }

    public static void appendItems() {
        initListIfNeeded();
        int size = list.size();
        for (int i = 0; i < 10; i++) {
            list.add("" + (size + i));
        }
    }
}

用于处理分页的数据源数据

DataSource used for handling pagination of data

public class MyDataSource extends PageKeyedDataSource<Integer, String> {

    public MyDataSource() {
    }

    @Override
    public void loadInitial(@NonNull LoadInitialParams<Integer> params, @NonNull LoadInitialCallback<Integer, String> callback) {
        callback.onResult(Api.pageItems(0, params.requestedLoadSize), -1, 1);
    }

    @Override
    public void loadBefore(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, String> callback) {
        callback.onResult(Api.pageItems(params.key, params.requestedLoadSize), params.key - 1);
    }

    @Override
    public void loadAfter(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, String> callback) {
        callback.onResult(Api.pageItems(params.key, params.requestedLoadSize), params.key + 1);
    }

}

对应的ViewModel类

The corresponding ViewModel class

public class MyViewModel extends ViewModel {

    public LiveData<PagedList<String>> list;

    public MyViewModel() {
        list = new LivePagedListBuilder<>(new DataSource.Factory<Integer, String>() {
            @Override
            public DataSource<Integer, String> create() {
                return new MyDataSource();
            }
        },  new PagedList.Config.Builder().setPageSize(20).setInitialLoadSizeHint(20).build()).build();
    }

    public void appendItems() {
        Api.appendItems();
    }
}

活动

public class PagedListActivity extends AppCompatActivity {

    private MyPagedListAdapter adapter;
    private MyViewModel viewModel;
    private RecyclerView recyclerView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_paged_list);
        adapter = new MyPagedListAdapter(LayoutInflater.from(this));

        recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(adapter);
        viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
        viewModel.list.observe(this, new Observer<PagedList<String>>() {
            @DebugLog
            @Override
            public void onChanged(PagedList<String> strings) {
                adapter.submitList(strings);
            }
        });
    }

    @DebugLog
    public void onClick(View view) {
        viewModel.appendItems();
    }
}

适配器

public class MyPagedListAdapter extends PagedListAdapter<String, MyPagedListAdapter.VH> {

    private LayoutInflater inflater;

    protected MyPagedListAdapter(LayoutInflater inflater) {
        super(DIFF_CALLBACK);
        this.inflater = inflater;
    }

    @NonNull
    @Override
    public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = inflater.inflate(R.layout.item_text, parent, false);
        return new VH(view);
    }

    @Override
    public void onBindViewHolder(@NonNull VH holder, int position) {
        holder.setData(getItem(position));
    }

    public class VH extends RecyclerView.ViewHolder {

        private final TextView txt;

        public VH(@NonNull View itemView) {
            super(itemView);
            txt = itemView.findViewById(R.id.txt);
        }

        public void setData(String text) {
            txt.setText(text);
        }
    }

    private static DiffUtil.ItemCallback<String> DIFF_CALLBACK = new DiffUtil.ItemCallback<String>() {
        @Override
        public boolean areItemsTheSame(@NonNull String oldItem, @NonNull String newItem) {
            return oldItem.equalsIgnoreCase(newItem);
        }

        @Override
        public boolean areContentsTheSame(@NonNull String oldItem, @NonNull String newItem) {
            return oldItem.equalsIgnoreCase(newItem);
        }
    };

}


推荐答案

从这里stacktrace:

From this stacktrace:

java.util.ConcurrentModificationException
    at java.util.AbstractList$SubAbstractList.size(AbstractList.java:360)

我们可以知道

a)当有人尝试修改列表,而列表迭代正在进行中时,应用程序崩溃

b),这发生在SubAbstractList实例上(当您调用
list时创建)。 subList(start,end);

a) app crashes when someone is trying to modify list while iteration over list is in process
b) this happens on SubAbstractList instance (that is created when you call list.subList(start, end);

应用程序崩溃,因为在修改原始列表之前修改之前创建的子列表不再有效(将项目追加到)原始列表

App crashes because sublist created before original list modifications is no longer valid, after you modify (append items to) originial list

而不是从返回 list.subList(start,end); Api#pageItems 尝试

返回 new ArrayList<>(list.subList(start,end));

Instead of returning list.subList(start, end); from Api#pageItems try
returning new ArrayList<>(list.subList(start, end));

要让RecyclerView显示更改,应调用 Adapter#notifyItemRangeInserte d 或RW适配器

For RecyclerView to display your changes, you should call Adapter#notifyItemRangeInserted or RW adapter

这篇关于Android:使用PagedList时如何添加项目和刷新列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆