Failing to load next data with android Paging library
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.
In my database I have total 25 call log record. The first 9 call log is showing in the list.
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.
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.
And the observe method of view model is getting called only once, the first time only.
I think I am doing something wrong.
Here is the code below
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
@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();
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;
Later I tried to make
private LiveData<List<CallLogItem>> callLogList;
to Paged list like
private LiveData<PagedList<CallLogItem>> callLogList;
But I found no proper way to transform into that.
android android-room android-livedata androidx android-paging
add a comment |
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.
In my database I have total 25 call log record. The first 9 call log is showing in the list.
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.
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.
And the observe method of view model is getting called only once, the first time only.
I think I am doing something wrong.
Here is the code below
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
@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();
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;
Later I tried to make
private LiveData<List<CallLogItem>> callLogList;
to Paged list like
private LiveData<PagedList<CallLogItem>> callLogList;
But I found no proper way to transform into that.
android android-room android-livedata androidx android-paging
add a comment |
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.
In my database I have total 25 call log record. The first 9 call log is showing in the list.
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.
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.
And the observe method of view model is getting called only once, the first time only.
I think I am doing something wrong.
Here is the code below
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
@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();
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;
Later I tried to make
private LiveData<List<CallLogItem>> callLogList;
to Paged list like
private LiveData<PagedList<CallLogItem>> callLogList;
But I found no proper way to transform into that.
android android-room android-livedata androidx android-paging
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.
In my database I have total 25 call log record. The first 9 call log is showing in the list.
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.
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.
And the observe method of view model is getting called only once, the first time only.
I think I am doing something wrong.
Here is the code below
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
@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();
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;
Later I tried to make
private LiveData<List<CallLogItem>> callLogList;
to Paged list like
private LiveData<PagedList<CallLogItem>> callLogList;
But I found no proper way to transform into that.
android android-room android-livedata androidx android-paging
android android-room android-livedata androidx android-paging
edited Dec 2 '18 at 7:32
Ifta
asked Nov 14 '18 at 10:14
IftaIfta
19339
19339
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
In order to be able to return a mapped PagedList
you should know that DataSource
and DataSource.Factory
has map()
and mapByPage()
.
You can map the DataSource Factory items with mapByPage()
instead using Transformation
, like this:
DataSource.Factory<Integer, CallLog> dataSourceFactoryCallLog = AppDatabase.get().callLogDao().getAllLivePaged();
DataSource.Factory<Integer, CallLogItem> dataSourceFactoryCallLogItem = dataSourceFactoryCallLog.mapByPage(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<PagedList<CallLogItem>> callLogItems = new LivePagedListBuilder<>(dataSourceFactoryCallLogItem, 3).build()
EDIT
According PagedList documentation
With placeholders, the PagedList is always the full size of the data set. get(N) returns the Nth item in the data set, or null if its not yet loaded.
Without null placeholders, the PagedList is the sublist of data that has already been loaded. The size of the PagedList is the number of currently loaded items, and get(N) returns the Nth loaded item. This is not necessarily the Nth item in the data set.
Placeholders are enabled by default, but can be disabled in two ways. They are disabled if the DataSource does not count its data set in its initial load, or if false is passed to
setEnablePlaceholders(boolean)
when building aPagedList.Config
.
You just need to create a PagedList.Config
and add this to LivePagedListBuilder
instantiation.
PagedList.Config pagedListConfig =
(new PagedList.Config.Builder())
.setEnablePlaceholders(false)
.setPageSize(3).build();
LiveData<PagedList<CallLogItem>> callLogItems = new LivePagedListBuilder<>(dataSourceFactoryCallLogItem, pagedListConfig).build()
I have tried and i found that, in my adapter refreshData method is called only once with full list size. List size is 25 but contains 9 actual data, others are null. How can I configure PagedList to load the next page in the data list?
– Ifta
Nov 15 '18 at 3:55
try to create aPagedList.Config
and add this toLivePagedListBuilder
instantiation.new LivePagedListBuilder<>(dataSourceFactoryCallLogItem, pagedListConfig).build()
– haroldolivieri
Nov 15 '18 at 8:55
change placeholders to false onPagedList.Config
like this.setEnablePlaceholders(false)
– haroldolivieri
Nov 15 '18 at 9:02
thanks. that would help removing null elements, i know. but the problem was wrong implementation of my adapter class. I had edited your answer to make it correct answer and was waiting for the edit to approve by peer review. But now I see the edit is gone.
– Ifta
Nov 15 '18 at 10:56
1
I think you can edit your question to let the problem more clear and after this create the right answer for that.
– haroldolivieri
Nov 17 '18 at 21:01
|
show 3 more comments
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);
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53297726%2ffailing-to-load-next-data-with-android-paging-library%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
In order to be able to return a mapped PagedList
you should know that DataSource
and DataSource.Factory
has map()
and mapByPage()
.
You can map the DataSource Factory items with mapByPage()
instead using Transformation
, like this:
DataSource.Factory<Integer, CallLog> dataSourceFactoryCallLog = AppDatabase.get().callLogDao().getAllLivePaged();
DataSource.Factory<Integer, CallLogItem> dataSourceFactoryCallLogItem = dataSourceFactoryCallLog.mapByPage(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<PagedList<CallLogItem>> callLogItems = new LivePagedListBuilder<>(dataSourceFactoryCallLogItem, 3).build()
EDIT
According PagedList documentation
With placeholders, the PagedList is always the full size of the data set. get(N) returns the Nth item in the data set, or null if its not yet loaded.
Without null placeholders, the PagedList is the sublist of data that has already been loaded. The size of the PagedList is the number of currently loaded items, and get(N) returns the Nth loaded item. This is not necessarily the Nth item in the data set.
Placeholders are enabled by default, but can be disabled in two ways. They are disabled if the DataSource does not count its data set in its initial load, or if false is passed to
setEnablePlaceholders(boolean)
when building aPagedList.Config
.
You just need to create a PagedList.Config
and add this to LivePagedListBuilder
instantiation.
PagedList.Config pagedListConfig =
(new PagedList.Config.Builder())
.setEnablePlaceholders(false)
.setPageSize(3).build();
LiveData<PagedList<CallLogItem>> callLogItems = new LivePagedListBuilder<>(dataSourceFactoryCallLogItem, pagedListConfig).build()
I have tried and i found that, in my adapter refreshData method is called only once with full list size. List size is 25 but contains 9 actual data, others are null. How can I configure PagedList to load the next page in the data list?
– Ifta
Nov 15 '18 at 3:55
try to create aPagedList.Config
and add this toLivePagedListBuilder
instantiation.new LivePagedListBuilder<>(dataSourceFactoryCallLogItem, pagedListConfig).build()
– haroldolivieri
Nov 15 '18 at 8:55
change placeholders to false onPagedList.Config
like this.setEnablePlaceholders(false)
– haroldolivieri
Nov 15 '18 at 9:02
thanks. that would help removing null elements, i know. but the problem was wrong implementation of my adapter class. I had edited your answer to make it correct answer and was waiting for the edit to approve by peer review. But now I see the edit is gone.
– Ifta
Nov 15 '18 at 10:56
1
I think you can edit your question to let the problem more clear and after this create the right answer for that.
– haroldolivieri
Nov 17 '18 at 21:01
|
show 3 more comments
In order to be able to return a mapped PagedList
you should know that DataSource
and DataSource.Factory
has map()
and mapByPage()
.
You can map the DataSource Factory items with mapByPage()
instead using Transformation
, like this:
DataSource.Factory<Integer, CallLog> dataSourceFactoryCallLog = AppDatabase.get().callLogDao().getAllLivePaged();
DataSource.Factory<Integer, CallLogItem> dataSourceFactoryCallLogItem = dataSourceFactoryCallLog.mapByPage(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<PagedList<CallLogItem>> callLogItems = new LivePagedListBuilder<>(dataSourceFactoryCallLogItem, 3).build()
EDIT
According PagedList documentation
With placeholders, the PagedList is always the full size of the data set. get(N) returns the Nth item in the data set, or null if its not yet loaded.
Without null placeholders, the PagedList is the sublist of data that has already been loaded. The size of the PagedList is the number of currently loaded items, and get(N) returns the Nth loaded item. This is not necessarily the Nth item in the data set.
Placeholders are enabled by default, but can be disabled in two ways. They are disabled if the DataSource does not count its data set in its initial load, or if false is passed to
setEnablePlaceholders(boolean)
when building aPagedList.Config
.
You just need to create a PagedList.Config
and add this to LivePagedListBuilder
instantiation.
PagedList.Config pagedListConfig =
(new PagedList.Config.Builder())
.setEnablePlaceholders(false)
.setPageSize(3).build();
LiveData<PagedList<CallLogItem>> callLogItems = new LivePagedListBuilder<>(dataSourceFactoryCallLogItem, pagedListConfig).build()
I have tried and i found that, in my adapter refreshData method is called only once with full list size. List size is 25 but contains 9 actual data, others are null. How can I configure PagedList to load the next page in the data list?
– Ifta
Nov 15 '18 at 3:55
try to create aPagedList.Config
and add this toLivePagedListBuilder
instantiation.new LivePagedListBuilder<>(dataSourceFactoryCallLogItem, pagedListConfig).build()
– haroldolivieri
Nov 15 '18 at 8:55
change placeholders to false onPagedList.Config
like this.setEnablePlaceholders(false)
– haroldolivieri
Nov 15 '18 at 9:02
thanks. that would help removing null elements, i know. but the problem was wrong implementation of my adapter class. I had edited your answer to make it correct answer and was waiting for the edit to approve by peer review. But now I see the edit is gone.
– Ifta
Nov 15 '18 at 10:56
1
I think you can edit your question to let the problem more clear and after this create the right answer for that.
– haroldolivieri
Nov 17 '18 at 21:01
|
show 3 more comments
In order to be able to return a mapped PagedList
you should know that DataSource
and DataSource.Factory
has map()
and mapByPage()
.
You can map the DataSource Factory items with mapByPage()
instead using Transformation
, like this:
DataSource.Factory<Integer, CallLog> dataSourceFactoryCallLog = AppDatabase.get().callLogDao().getAllLivePaged();
DataSource.Factory<Integer, CallLogItem> dataSourceFactoryCallLogItem = dataSourceFactoryCallLog.mapByPage(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<PagedList<CallLogItem>> callLogItems = new LivePagedListBuilder<>(dataSourceFactoryCallLogItem, 3).build()
EDIT
According PagedList documentation
With placeholders, the PagedList is always the full size of the data set. get(N) returns the Nth item in the data set, or null if its not yet loaded.
Without null placeholders, the PagedList is the sublist of data that has already been loaded. The size of the PagedList is the number of currently loaded items, and get(N) returns the Nth loaded item. This is not necessarily the Nth item in the data set.
Placeholders are enabled by default, but can be disabled in two ways. They are disabled if the DataSource does not count its data set in its initial load, or if false is passed to
setEnablePlaceholders(boolean)
when building aPagedList.Config
.
You just need to create a PagedList.Config
and add this to LivePagedListBuilder
instantiation.
PagedList.Config pagedListConfig =
(new PagedList.Config.Builder())
.setEnablePlaceholders(false)
.setPageSize(3).build();
LiveData<PagedList<CallLogItem>> callLogItems = new LivePagedListBuilder<>(dataSourceFactoryCallLogItem, pagedListConfig).build()
In order to be able to return a mapped PagedList
you should know that DataSource
and DataSource.Factory
has map()
and mapByPage()
.
You can map the DataSource Factory items with mapByPage()
instead using Transformation
, like this:
DataSource.Factory<Integer, CallLog> dataSourceFactoryCallLog = AppDatabase.get().callLogDao().getAllLivePaged();
DataSource.Factory<Integer, CallLogItem> dataSourceFactoryCallLogItem = dataSourceFactoryCallLog.mapByPage(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<PagedList<CallLogItem>> callLogItems = new LivePagedListBuilder<>(dataSourceFactoryCallLogItem, 3).build()
EDIT
According PagedList documentation
With placeholders, the PagedList is always the full size of the data set. get(N) returns the Nth item in the data set, or null if its not yet loaded.
Without null placeholders, the PagedList is the sublist of data that has already been loaded. The size of the PagedList is the number of currently loaded items, and get(N) returns the Nth loaded item. This is not necessarily the Nth item in the data set.
Placeholders are enabled by default, but can be disabled in two ways. They are disabled if the DataSource does not count its data set in its initial load, or if false is passed to
setEnablePlaceholders(boolean)
when building aPagedList.Config
.
You just need to create a PagedList.Config
and add this to LivePagedListBuilder
instantiation.
PagedList.Config pagedListConfig =
(new PagedList.Config.Builder())
.setEnablePlaceholders(false)
.setPageSize(3).build();
LiveData<PagedList<CallLogItem>> callLogItems = new LivePagedListBuilder<>(dataSourceFactoryCallLogItem, pagedListConfig).build()
edited Nov 15 '18 at 9:23
answered Nov 14 '18 at 11:47
haroldolivieriharoldolivieri
329214
329214
I have tried and i found that, in my adapter refreshData method is called only once with full list size. List size is 25 but contains 9 actual data, others are null. How can I configure PagedList to load the next page in the data list?
– Ifta
Nov 15 '18 at 3:55
try to create aPagedList.Config
and add this toLivePagedListBuilder
instantiation.new LivePagedListBuilder<>(dataSourceFactoryCallLogItem, pagedListConfig).build()
– haroldolivieri
Nov 15 '18 at 8:55
change placeholders to false onPagedList.Config
like this.setEnablePlaceholders(false)
– haroldolivieri
Nov 15 '18 at 9:02
thanks. that would help removing null elements, i know. but the problem was wrong implementation of my adapter class. I had edited your answer to make it correct answer and was waiting for the edit to approve by peer review. But now I see the edit is gone.
– Ifta
Nov 15 '18 at 10:56
1
I think you can edit your question to let the problem more clear and after this create the right answer for that.
– haroldolivieri
Nov 17 '18 at 21:01
|
show 3 more comments
I have tried and i found that, in my adapter refreshData method is called only once with full list size. List size is 25 but contains 9 actual data, others are null. How can I configure PagedList to load the next page in the data list?
– Ifta
Nov 15 '18 at 3:55
try to create aPagedList.Config
and add this toLivePagedListBuilder
instantiation.new LivePagedListBuilder<>(dataSourceFactoryCallLogItem, pagedListConfig).build()
– haroldolivieri
Nov 15 '18 at 8:55
change placeholders to false onPagedList.Config
like this.setEnablePlaceholders(false)
– haroldolivieri
Nov 15 '18 at 9:02
thanks. that would help removing null elements, i know. but the problem was wrong implementation of my adapter class. I had edited your answer to make it correct answer and was waiting for the edit to approve by peer review. But now I see the edit is gone.
– Ifta
Nov 15 '18 at 10:56
1
I think you can edit your question to let the problem more clear and after this create the right answer for that.
– haroldolivieri
Nov 17 '18 at 21:01
I have tried and i found that, in my adapter refreshData method is called only once with full list size. List size is 25 but contains 9 actual data, others are null. How can I configure PagedList to load the next page in the data list?
– Ifta
Nov 15 '18 at 3:55
I have tried and i found that, in my adapter refreshData method is called only once with full list size. List size is 25 but contains 9 actual data, others are null. How can I configure PagedList to load the next page in the data list?
– Ifta
Nov 15 '18 at 3:55
try to create a
PagedList.Config
and add this to LivePagedListBuilder
instantiation. new LivePagedListBuilder<>(dataSourceFactoryCallLogItem, pagedListConfig).build()
– haroldolivieri
Nov 15 '18 at 8:55
try to create a
PagedList.Config
and add this to LivePagedListBuilder
instantiation. new LivePagedListBuilder<>(dataSourceFactoryCallLogItem, pagedListConfig).build()
– haroldolivieri
Nov 15 '18 at 8:55
change placeholders to false on
PagedList.Config
like this .setEnablePlaceholders(false)
– haroldolivieri
Nov 15 '18 at 9:02
change placeholders to false on
PagedList.Config
like this .setEnablePlaceholders(false)
– haroldolivieri
Nov 15 '18 at 9:02
thanks. that would help removing null elements, i know. but the problem was wrong implementation of my adapter class. I had edited your answer to make it correct answer and was waiting for the edit to approve by peer review. But now I see the edit is gone.
– Ifta
Nov 15 '18 at 10:56
thanks. that would help removing null elements, i know. but the problem was wrong implementation of my adapter class. I had edited your answer to make it correct answer and was waiting for the edit to approve by peer review. But now I see the edit is gone.
– Ifta
Nov 15 '18 at 10:56
1
1
I think you can edit your question to let the problem more clear and after this create the right answer for that.
– haroldolivieri
Nov 17 '18 at 21:01
I think you can edit your question to let the problem more clear and after this create the right answer for that.
– haroldolivieri
Nov 17 '18 at 21:01
|
show 3 more comments
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);
add a comment |
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);
add a comment |
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);
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);
answered Dec 2 '18 at 7:38
IftaIfta
19339
19339
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53297726%2ffailing-to-load-next-data-with-android-paging-library%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown