Android:使用PagedList时如何添加项目和刷新列表? [英] Android: how to add items and refresh list when using 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屋!