I am trying to use paging library with newer versions. I am using volley to fetch my data from network. Whenever I fetch data from network, the data is fetched but when the call goes to observer the list size shown there is zero. I am unsure what I am doing wrong.
I am new to android so don't know much about paging. Its been days since I m trying but still unable to figure it out.
My gradle is as follows
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
defaultConfig {
applicationId "com.example.athansys.mypagingapplication"
minSdkVersion 22
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:support-v4:27.1.1'
implementation 'com.android.support:cardview-v7:27.1.1'
implementation 'com.android.support:recyclerview-v7:27.1.1'
implementation 'com.android.volley:volley:1.1.0'
implementation 'com.google.code.gson:gson:2.8.1'
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation "android.arch.paging:runtime:1.0.1"
implementation "android.arch.lifecycle:runtime:1.1.1"
implementation "android.arch.lifecycle:extensions:1.1.1"
annotationProcessor "android.arch.lifecycle:compiler:1.1.1"
}
My MainActivity looks like:
package com.example.athansys.mypagingapplication;
import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import android.arch.paging.PagedList;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
public class MainActivity extends AppCompatActivity {
private MyPatientAdapter mPatientAdapter;
private RecyclerView mRecyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FilterModel viewModel = ViewModelProviders.of(this).get(FilterModel.class);
viewModel.getData(this).observe(this, new Observer<PagedList<FilterPatientList>>() {
@Override
public void onChanged(@Nullable PagedList<FilterPatientList> results) {
mPatientAdapter.submitList(results);
//mPatientAdapter.setList(results);
mPatientAdapter.notifyDataSetChanged();
mRecyclerView.setAdapter(mPatientAdapter);
}
});
}
private void setAdapter() {
mRecyclerView = findViewById(R.id.my_patient_recycler_view);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
mPatientAdapter = new MyPatientAdapter();
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setAdapter(mPatientAdapter);
}
}
FilterModel class is as follows:
package com.example.athansys.mypagingapplication;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.ViewModel;
import android.arch.paging.LivePagedListBuilder;
import android.arch.paging.PagedList;
import android.content.Context;
import android.util.Log;
public class FilterModel extends ViewModel {
private LiveData<PagedList<FilterPatientList>> listLiveData;
LiveData<PagedList<FilterPatientList>> getData(Context context) {
if (listLiveData == null) {
PagedList.Config pagedListConfig =
(new PagedList.Config.Builder()).setEnablePlaceholders(false)
.setPrefetchDistance(5)
.setPageSize(1).build();
listLiveData = new LivePagedListBuilder<>
(new MyPatientPagedListProvider(context)
.getAll()
, pagedListConfig).
build();
}
return listLiveData;
}
}
MyProvider class is:
package com.example.athansys.mypagingapplication;
import android.arch.paging.DataSource;
import android.arch.paging.LivePagedListProvider;
import android.content.Context;
import android.util.Log;
import java.util.List;
public class MyPatientPagedListProvider {
Context mBaseContext;
public MyPatientPagedListProvider(Context context) {
mBaseContext = context;
dataClass.getContextInstance(context);
}
private static final String TAG = MyPatientPagedListProvider.class.getName();
MyPatientData dataClass = new MyPatientData() {
@Override
public List<FilterPatientList> convertToItems(List<FilterPatientList> result, int size) {
return result;
}
};
public LivePagedListProvider<Integer, FilterPatientList> getAll() {
return new LivePagedListProvider<Integer, FilterPatientList>() {
@Override
protected DataSource<Integer, FilterPatientList> createDataSource() {
return dataClass;
}
};
}
}
MyDataSource is as follows:
package com.example.athansys.mypagingapplication;
import android.arch.paging.TiledDataSource;
import android.content.Context;
import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.google.gson.Gson;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class MyPatientData extends TiledDataSource<FilterPatientList> {
private Context mContext;
private List<FilterPatientList> patientList;
@Override
public int countItems() {
return 10;
}
@Override
public List<FilterPatientList> loadRange(int startPosition, int count) {
String url = "My URl";
return postStringRequestForMyPatient(url);
}
public List<FilterPatientList> postStringRequestForMyPatient(String url) {
StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(response);
String data = jsonObject.getString("patientsfordoctor");
mPatientsForDoctor = new Gson().fromJson(data, PatientsForDoctor.class);
mPatientList = new ArrayList<>();
mPatientList.addAll(mPatientsForDoctor.getPatientList());
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
}) {
@Override
protected Map<String, String> getParams() throws AuthFailureError {
return super.getParams();
}
@Override
public String getBodyContentType() {
return super.getBodyContentType();
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return new HashMap<>();
}
};
stringRequest.setRetryPolicy(new DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
Volley.newRequestQueue(mContext).add(stringRequest);
}
void getContextInstance(Context context) {
mContext = context;
}
public abstract List<FilterPatientList> convertToItems(List<FilterPatientList> result, int size);
}
My Adapter class
package com.example.athansys.mypagingapplication;
import android.arch.paging.PagedListAdapter;
import android.support.annotation.NonNull;
import android.support.v7.util.DiffUtil;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class MyPatientAdapter extends PagedListAdapter<FilterPatientList, MyPatientAdapter.PatientViewHolder> {
protected MyPatientAdapter() {
super(FilterPatientList.DIFF_CALLBACK);
}
@NonNull
@Override
public PatientViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(@NonNull PatientViewHolder holder, int position) {
}
class PatientViewHolder extends RecyclerView.ViewHolder {
TextView patientName, patientPhoneNumber, genderAge;
PatientViewHolder(View itemView) {
super(itemView);
}
}
}
My POJO(MODEL CLASSES ARE AS FOLLOWS)
FilterPatientList class:
package com.example.athansys.mypagingapplication;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v7.util.DiffUtil;
import com.google.gson.annotations.SerializedName;
public class FilterPatientList implements Parcelable {
private long patientId;
private Patient patientDetails;
protected FilterPatientList(Parcel in) {
patientId = in.readLong();
patientDetails = in.readParcelable(Patient.class.getClassLoader());
}
public static final Creator<FilterPatientList> CREATOR = new Creator<FilterPatientList>() {
@Override
public FilterPatientList createFromParcel(Parcel in) {
return new FilterPatientList(in);
}
@Override
public FilterPatientList[] newArray(int size) {
return new FilterPatientList[size];
}
};
public long getPatientId() {
return patientId;
}
public void setPatientId(long patientId) {
this.patientId = patientId;
}
public Patient getPatientDetails() {
return patientDetails;
}
public void setPatientDetails(Patient patientDetails) {
this.patientDetails = patientDetails;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(patientId);
dest.writeParcelable(patientDetails, flags);
}
public static final DiffUtil.ItemCallback<FilterPatientList> DIFF_CALLBACK = new DiffUtil.ItemCallback<FilterPatientList>() {
@Override
public boolean areItemsTheSame(FilterPatientList oldItem, FilterPatientList newItem) {
return false;
}
@Override
public boolean areContentsTheSame(FilterPatientList oldItem, FilterPatientList newItem) {
return false;
}
};
}
PATIENT CLASS:
package com.example.athansys.mypagingapplication;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.annotations.SerializedName;
public class Patient implements Parcelable{
private long localPatientId;
private long apptDoctorId;
private long patientId;
private boolean isLocalPatient;
private String firstName;
private String lastName;
private String phoneNumber;
private String email;
private String dob;
private int age;
private int height;
private int weight;
private String patientSex;
private String patientSystemRegistrationDate;
private int bloodGroup;
protected Patient(Parcel in) {
localPatientId = in.readLong();
apptDoctorId = in.readLong();
patientId = in.readLong();
isLocalPatient = in.readByte() != 0;
firstName = in.readString();
lastName = in.readString();
phoneNumber = in.readString();
email = in.readString();
dob = in.readString();
age = in.readInt();
height = in.readInt();
weight = in.readInt();
patientSex = in.readString();
patientSystemRegistrationDate = in.readString();
bloodGroup = in.readInt();
}
public static final Creator<Patient> CREATOR = new Creator<Patient>() {
@Override
public Patient createFromParcel(Parcel in) {
return new Patient(in);
}
@Override
public Patient[] newArray(int size) {
return new Patient[size];
}
};
public long getLocalPatientId() {
return localPatientId;
}
public void setLocalPatientId(long localPatientId) {
this.localPatientId = localPatientId;
}
public long getApptDoctorId() {
return apptDoctorId;
}
public void setApptDoctorId(long apptDoctorId) {
this.apptDoctorId = apptDoctorId;
}
public long getPatientId() {
return patientId;
}
public void setPatientId(long patientId) {
this.patientId = patientId;
}
public boolean isLocalPatient() {
return isLocalPatient;
}
public void setLocalPatient(boolean localPatient) {
isLocalPatient = localPatient;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getDob() {
return dob;
}
public void setDob(String dob) {
this.dob = dob;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public String getPatientSex() {
return patientSex;
}
public void setPatientSex(String patientSex) {
this.patientSex = patientSex;
}
public String getPatientSystemRegistrationDate() {
return patientSystemRegistrationDate;
}
public void setPatientSystemRegistrationDate(String patientSystemRegistrationDate) {
this.patientSystemRegistrationDate = patientSystemRegistrationDate;
}
public int getBloodGroup() {
return bloodGroup;
}
public void setBloodGroup(int bloodGroup) {
this.bloodGroup = bloodGroup;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(localPatientId);
dest.writeLong(apptDoctorId);
dest.writeLong(patientId);
dest.writeByte((byte) (isLocalPatient ? 1 : 0));
dest.writeString(firstName);
dest.writeString(lastName);
dest.writeString(phoneNumber);
dest.writeString(email);
dest.writeString(dob);
dest.writeInt(age);
dest.writeInt(height);
dest.writeInt(weight);
dest.writeString(patientSex);
dest.writeString(patientSystemRegistrationDate);
dest.writeInt(bloodGroup);
}
}
When I receive data from network in Data source class(MyPatientData) the call automatically goes to observer in main activity. There the list size shown is zero whereas the list when fetched from network had a size of 10 items.
Can you please help me out. I am really stuck for days with no clue what to do next. Thanks a lot in advance. :)
You can implement BoundaryCallback in LivePagedListBuilder. It contains method onZeroItemsLoaded.
listLiveData = new LivePagedListBuilder<>
(new MyPatientPagedListProvider(context)
.getAll()
, pagedListConfig)
.setBoundaryCallback(new PagedList.BoundaryCallback() {
@Override
public void onZeroItemsLoaded() {
super.onZeroItemsLoaded();
// do smth here. For example, post boolean value to MutableLiveData to notify activity //that result is empty
}
})
.build();
To get the size of the item inserted or size of that RecyclerView, we need to register an AdapterDataObserver
to our RecyclerView.
1) Create an AdapterDataObserver and override the functions you want.
public class SearchListAdapterDataObserver extends RecyclerView.AdapterDataObserver {
private RecyclerView mRecyclerView;
private ChangeListener mChangeListener;
public SearchListAdapterDataObserver(RecyclerView view, ChangeListener changeListener){
this.mRecyclerView = view;
this.mChangeListener = changeListener;
}
@Override
public void onChanged() {
super.onChanged();
sendItemCount();
}
private void sendItemCount() {
if(mRecyclerView.getAdapter() != null) {
mChangeListener.onChanged(getSize());
}
}
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
super.onItemRangeInserted(positionStart, itemCount);
sendItemCount();
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount) {
super.onItemRangeChanged(positionStart, itemCount);
sendItemCount();
}
@Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
super.onItemRangeRemoved(positionStart, itemCount);
sendItemCount();
}
public int getSize() {
if(mRecyclerView.getAdapter() != null) {
return mRecyclerView.getAdapter().getItemCount();
}
return 0;
}
public interface ChangeListener {
void onChanged(int size);
}
}
2) Register it to your adapter and listen to the changes.
if(mViewModel.getSearchPaginatedAdapter() != null){
mViewModel.getSearchPaginatedAdapter().registerAdapterDataObserver
(new SearchListAdapterDataObserver(mRecyclerView, new SearchListAdapterDataObserver.ChangeListener() {
@Override
public void onChanged(int size) {
onListChanges(size);
}
}));
}
Here is the simple solution of pagination .
First time private void jsonRequestList(int pageCount) {
will called with pageCount=1
and next time increment with 2,3,4...
Inside private void jsonRequestList(int pageCount) {
method (JSON REQUEST) first time if (!isScrollCalled) {
will called & next time else
block will called.
Activity/Fragment :
private boolean loading = false;
private boolean isScrollCalled;
int isLastPage = 10;
int pageCount = 1;
//Paigination
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
int lastvisibleitemposition = linearLayoutManager.findLastVisibleItemPosition();
if (lastvisibleitemposition == adapter.getItemCount() - 1) {
if (!loading && pageCount != isLastPage) {
loading = true;
jsonRequestList(++pageCount);
isScrollCalled = Boolean.TRUE;
}
}
}
});
private void jsonRequestList(int pageCount) {
//Json Request
if (!isScrollCalled) {
adapter = new FlowerListAdapter(FlowerListActivity.this, list);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
// Log.e("LIST_SIZE", "" + list.size());
} else {
adapter.updateList(list);
//Log.e("LIST_SIZE", "" + list.size());
}
loading = false;
}
Recycler Adapter :
ArrayList<YourModelClass> list;
Context context;
//Pagination
public void updateList(ArrayList<YourModelClass> list) {
this.list.addAll(list);
this.notifyDataSetChanged();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With