无法使用android Paging库加载下一个数据 [英] Failing to load next data with android Paging library
问题描述
我正在尝试使用Room-Paging-LiveData-ViewModel显示呼叫日志列表。
如果不分页,我的代码将运行完美。我也想使用分页。
I am trying to show call log list using Room-Paging-LiveData-ViewModel. Without paging my code works perfectly. And I want to use paging also.
在我的数据库中,我总共有25条通话记录。前9个通话记录显示在列表中。
In my database I have total 25 call log record. The first 9 call log is showing in the list.
通过调试,我发现通过 Dao
在视图模型中读取数据时,它返回的是大小为25的列表。但是其中只有前9个非null。列表中的所有其他条目均为空。
By debugging I found that while reading data in view model via Dao
, it is returning list of size 25. But only first 9 of these are non null. All other entries in the list is null.
我希望由于这是一个分页的
列表,因此空数据将很快刷新。 。但是问题是null永远不会被
有效数据刷新。
I am expecting the null data will refresh soon as this is a paged list. But the problem is the null are never getting refreshed with valid data.
并且视图模型的watch方法正在获取只打过一次,只有第一次。
And the observe method of view model is getting called only once, the first time only.
我认为我做错了什么。
I think I am doing something wrong.
以下是代码
片段
The fragment
public class CallLogListFragment extends Fragment {
private static final String TAG = "RecentCallsFragment";
public static String getTAG() {
return TAG;
}
public static Fragment newInstance() {
return new CallLogListFragment();
}
public CallLogListFragment() {
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
FragmentCallLogListBinding binding = DataBindingUtil.inflate(inflater, R.layout.fragment_call_log_list, container, false);
CallLogListAdapter adapter = new CallLogListAdapter();
binding.list.setAdapter(adapter);
CallLogListViewModel model = ViewModelProviders.of(this).get(CallLogListViewModel.class);
model.getCallLogList().observe(this, adapter::refreshData);
return binding.getRoot();
}
}
适配器
The Adapter
public class CallLogListAdapter extends PagedListAdapter<CallLogItem, CallLogListAdapter.ViewHolder> {
CallLogListAdapter() {
super(DIFF_CALLBACK);
}
void refreshData(List<CallLogItem> data) {
DiffUtil.DiffResult calculatedDiff = DiffUtil.calculateDiff(new CallLogListDiffUtilCallBack(this.data, data));
this.data.clear();
this.data.addAll(data);
calculatedDiff.dispatchUpdatesTo(this);
}
private List<CallLogItem> data = new ArrayList<>();
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ViewHolder(DataBindingUtil.inflate(
LayoutInflater.from(parent.getContext()),
R.layout.call_log_list_single_item,
parent, false
));
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
CallLogItem item = data.get(position);
holder.binding.setCallLog(item);
}
@Override
public int getItemCount() {
return data.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
public CallLogListSingleItemBinding binding;
public ViewHolder(@NonNull CallLogListSingleItemBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
}
private static DiffUtil.ItemCallback<CallLogItem> DIFF_CALLBACK =
new DiffUtil.ItemCallback<CallLogItem>() {
@Override
public boolean areItemsTheSame(CallLogItem oldItem, CallLogItem newItem) {
return oldItem.getHeaderDateVisibility() == newItem.getHeaderDateVisibility()
&& oldItem.getCallId().equals(newItem.getCallId());
}
@Override
public boolean areContentsTheSame(@NonNull CallLogItem oldItem, @NonNull CallLogItem newItem) {
return areItemsTheSame(oldItem, newItem);
}
};
}
The Dao
The Dao
@Dao
public interface CallLogDao extends BaseDao<CallLog>{
@Query("SELECT * FROM log")
List<CallLog> getAll();
@Query("SELECT * FROM log WHERE number=:number")
CallLog findByName(String number);
@Query("SELECT * FROM log order by date desc")
LiveData<List<CallLog>> getAllLive();
@Query("SELECT * FROM log order by date desc")
DataSource.Factory<Integer, CallLog> getAllLivePaged();
}
ViewModel
The ViewModel
public class CallLogListViewModel extends ViewModel {
private LiveData<List<CallLogItem>> callLogList;
public CallLogListViewModel() {
callLogList = Transformations.map(new LivePagedListBuilder<>(AppDatabase.get().callLogDao().getAllLivePaged(), 3).build(), input -> {
List<CallLogItem> list = new ArrayList<>();
for (int i = 0; i < input.size(); i++) {
boolean isHeader = true;
CallLog callLog = input.get(i);
if(callLog!=null) {
if (i > 0) {
CallLog previousCallLog = input.get(i - 1);
if(previousCallLog!=null) {
isHeader = TimeFormat.isDifferentDate(callLog.date, previousCallLog.date);
}
}
list.add(CallLogItem.Companion.from(callLog, isHeader));
}
}
return list;
});
}
LiveData<List<CallLogItem>> getCallLogList() {
return callLogList;
}
}
后来我尝试制作
private LiveData<List<CallLogItem>> callLogList;
到
private LiveData<PagedList<CallLogItem>> callLogList;
但是我没有找到合适的方法来转换成那个。
But I found no proper way to transform into that.
推荐答案
对于分页列表适配器,有两点需要注意。
1.数据将在内部处理,无需声明任何数据结构即可手动处理数据。
2. PagedListAdapter
中有一个名为 submitList
的默认方法。有必要通过该方法将页面列表提交给适配器。
For paged list adapter there is 2 thing to note.
1. Data will be handled internally and no need to declare any data structure to handle data manually.
2. There is a default method called submitList
in PagedListAdapter
. It is necessary to submit paged list over that method to the adapter.
修改后的适配器
Modified adapter
public class CallLogListAdapter extends PagedListAdapter<CallLogItem, CallLogListAdapter.ViewHolder> {
private Context context;
CallLogListAdapter(Context context) {
super(DIFF_CALLBACK);
this.context = context;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ViewHolder(DataBindingUtil.inflate(
LayoutInflater.from(parent.getContext()),
R.layout.call_log_list_single_item,
parent, false
));
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
CallLogItem item = getItem(position);
if (item != null) {
holder.binding.setCallLog(item);
ImageUtil.setImage(holder.binding.ivProfileImage, item.getImageUrl(), item.getName());
} else {
holder.binding.invalidateAll();
}
}
class ViewHolder extends RecyclerView.ViewHolder {
public CallLogListSingleItemBinding binding;
public ViewHolder(@NonNull CallLogListSingleItemBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
}
private static DiffUtil.ItemCallback<CallLogItem> DIFF_CALLBACK =
new DiffUtil.ItemCallback<CallLogItem>() {
@Override
public boolean areItemsTheSame(CallLogItem oldItem, CallLogItem newItem) {
return oldItem.getHeaderDateVisibility() == newItem.getHeaderDateVisibility()
&& oldItem.getCallId()!=null && oldItem.getCallId().equals(newItem.getCallId());
}
@Override
public boolean areContentsTheSame(@NonNull CallLogItem oldItem, @NonNull CallLogItem newItem) {
return areItemsTheSame(oldItem, newItem);
}
};
}
修改后的数据传递给适配器
Modified Data passing to adapter
CallLogListViewModel model = ViewModelProviders.of(this).get(CallLogListViewModel.class);
model.getCallLogList().observe(this, adapter::submitList);
这篇关于无法使用android Paging库加载下一个数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!