Architecture Components

Android Paging Library

Welcome to implementing paging library. In this post, I’m going to discuss what is the paging library used for? How does it work? what are the advantages? and will learn implementation step of android paging library. So let’s get started

Introduction

What is paging and What is need of paging library. As you see in figure on right side represent a RecyclerView. Paging does, meaning the loading data for list in piecemeal. Basically, loading 3 items at a time in this image. We could load 10 at a time or 50 at a time. If you load all 1000 items once it will very slow and smash the user experience.

Android paging library makes it easy to load data gradually and gracefully within our app’s RecyclerView. It helps in loading and displaying data efficiently in chunk.

Paging Library Example

In this diagram, File have to be data source and from the data source you can do anythings such as call web API or database call, we can do anythings to get data. From that we get the PagedList after that creates page list adapter, which than populate our RecyclerView

Advantages of Paging Library

  • Paging library data request consumes less network bandwidth and fewer system resources. So the user needed a small data plan will appreciate a data conscious app .
  • App gives quick response even during the data update and refresh and also continue to respond quickly to the user input.

Technology Used

Following technology, we are using in this android app tutorials. Prerequisites are, you have to knowledge of below android component.

Step to implement Android Paging Library

  • Project Creation & Set Up
  • Create Models
  • Set Up Retrofit Client
  • Create a Data Source
  • Create a DataSource Factory
  • Setup ViewModel
  • Create a PagedListAdapter
  • Add Paging Stuff in MainActivity
  • Conclusion   

Implementation of the Paging Library Sample

1. Project Creation & Set Up

Let’s move to Android Studio and create a java android project. After project creation, You have to add certain dependency for this android app tutorial.

1.1 Let’s open the app level gradle file and add below dependencies

Using Paging, first of all, we need to add paging library dependency in gradle. Apart from this you need to some more dependencies such as LiveData, Retrofit etc.

  def lifecycle_version = "1.1.1"
  def paging_version = "1.0.1"
  def glide_version = "4.9.0"
  def constraint_version = "1.1.3"
  def retrofit_version = "2.4.0"
  def support_version = "28.0.0"

  // paging library
  implementation "android.arch.paging:runtime:$paging_version"

  // lifecycle
  implementation "android.arch.lifecycle:extensions:$lifecycle_version"
  annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version"

  // glide for image
  implementation "com.github.bumptech.glide:glide:$glide_version"
  annotationProcessor "com.github.bumptech.glide:compiler:$glide_version"

  // constraint layout
  implementation "com.android.support.constraint:constraint-layout:$constraint_version"

  // retrofit
  implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
  implementation 'com.squareup.retrofit2:converter-gson:2.4.0'

  // design and recyclerview
  implementation "com.android.support:recyclerview-v7:$support_version"
  implementation "com.android.support:cardview-v7:$support_version"
  implementation "com.android.support:design:$support_version"
1.2 Enable Data binding

Set enable true data binding in android tag in the app/ build.gradle

  dataBinding{
    enabled=true
  }
1.3 Add Internet Permission

In this android app tutorial we fetch data from server, so let’s add INTERNET uses permission in AndroidManifest.

  <uses-permission android:name="android.permission.INTERNET"/>

2. Let’s create a model classes and makes it Parcelable

In this tutorial, we get data from server. The JSON response is live below –

{
  "page": 1,
  "per_page": 3,
  "total": 12,
  "total_pages": 4,
  "data": [
    {
      "id": 1,
      "email": "george.bluth@reqres.in",
      "first_name": "George",
      "last_name": "Bluth",
      "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/calebogden/128.jpg"
    },
    {
      "id": 2,
      "email": "janet.weaver@reqres.in",
      "first_name": "Janet",
      "last_name": "Weaver",
      "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg"
    },
    {
      "id": 3,
      "email": "emma.wong@reqres.in",
      "first_name": "Emma",
      "last_name": "Wong",
      "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/olegpogodaev/128.jpg"
    }
  ]
}
2.1 Let’s create a model class for UserDBResponse

I’m creating two models class one for upper JSON object second for inner data JSON object. Let’s creates a class for an upper model class named is UserDBResponse.

package com.android.paginglibrary.model;

import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.List;

/**
 * Created by Morris on 03,June,2019
 */
public class UserDBResponse implements Parcelable {

  @SerializedName("page")
  @Expose
  private Integer page;
  @SerializedName("per_page")
  @Expose
  private Integer perPage;
  @SerializedName("total")
  @Expose
  private Integer total;
  @SerializedName("total_pages")
  @Expose
  private Integer totalPages;
  @SerializedName("data")
  @Expose
  private List<User> users = null;
  public final static Parcelable.Creator<UserDBResponse> CREATOR = new Creator<UserDBResponse>() {

    @SuppressWarnings({
        "unchecked"
    })
    public UserDBResponse createFromParcel(Parcel in) {
      return new UserDBResponse(in);
    }

    public UserDBResponse[] newArray(int size) {
      return (new UserDBResponse[size]);
    }
  };

  protected UserDBResponse(Parcel in) {
    this.page = ((Integer) in.readValue((Integer.class.getClassLoader())));
    this.perPage = ((Integer) in.readValue((Integer.class.getClassLoader())));
    this.total = ((Integer) in.readValue((Integer.class.getClassLoader())));
    this.totalPages = ((Integer) in.readValue((Integer.class.getClassLoader())));
    in.readList(this.users, (java.lang.Object.class.getClassLoader()));
  }

  public UserDBResponse() {
  }

  public Integer getPage() {
    return page;
  }

  public void setPage(Integer page) {
    this.page = page;
  }

  public Integer getPerPage() {
    return perPage;
  }

  public void setPerPage(Integer perPage) {
    this.perPage = perPage;
  }

  public Integer getTotal() {
    return total;
  }

  public void setTotal(Integer total) {
    this.total = total;
  }

  public Integer getTotalPages() {
    return totalPages;
  }

  public void setTotalPages(Integer totalPages) {
    this.totalPages = totalPages;
  }

  public List<User> getUsers() {
    return users;
  }

  public void setUsers(List<User> data) {
    this.users = data;
  }

  public void writeToParcel(Parcel dest, int flags) {
    dest.writeValue(page);
    dest.writeValue(perPage);
    dest.writeValue(total);
    dest.writeValue(totalPages);
    dest.writeList(users);
  }

  public int describeContents() {
    return 0;
  }
}
2.2 Now create model for user object named is User for inner JSON data
package com.android.paginglibrary.model;

import android.databinding.BaseObservable;
import android.databinding.Bindable;
import android.databinding.BindingAdapter;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v7.util.DiffUtil;
import android.widget.ImageView;
import com.android.paginglibrary.BR;
import com.android.paginglibrary.R;
import com.bumptech.glide.Glide;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class User extends BaseObservable implements Parcelable {

  @SerializedName("id")
  @Expose
  private Integer id;
  @SerializedName("email")
  @Expose
  private String email;
  @SerializedName("first_name")
  @Expose
  private String firstName;
  @SerializedName("last_name")
  @Expose
  private String lastName;
  @SerializedName("avatar")
  @Expose
  private String avatar;

  @BindingAdapter({ "avatar" })
  public static void loadImage(ImageView imageView, String imageURL) {

    Glide.with(imageView.getContext())
        .load(imageURL)
        .placeholder(R.drawable.loading)
        .into(imageView);
  }

  public final static Parcelable.Creator<User> CREATOR = new Creator<User>() {

    @SuppressWarnings({
        "unchecked"
    })
    public User createFromParcel(Parcel in) {
      return new User(in);
    }

    public User[] newArray(int size) {
      return (new User[size]);
    }
  };

  protected User(Parcel in) {
    this.id = ((Integer) in.readValue((Integer.class.getClassLoader())));
    this.email = ((String) in.readValue((String.class.getClassLoader())));
    this.firstName = ((String) in.readValue((String.class.getClassLoader())));
    this.lastName = ((String) in.readValue((String.class.getClassLoader())));
    this.avatar = ((String) in.readValue((String.class.getClassLoader())));
  }

  /**
   * No args constructor for use in serialization
   */
  public User() {
  }

  /**
   *
   * @param id
   * @param lastName
   * @param email
   * @param avatar
   * @param firstName
   */
  public User(Integer id, String email, String firstName, String lastName, String avatar) {
    super();
    this.id = id;
    this.email = email;
    this.firstName = firstName;
    this.lastName = lastName;
    this.avatar = avatar;
  }

  @Bindable
  public Integer getId() {
    return id;
  }

  public void setId(Integer id) {
    this.id = id;
    notifyPropertyChanged(BR.id);
  }

  public User withId(Integer id) {
    this.id = id;
    return this;
  }

  @Bindable
  public String getEmail() {
    return email;
  }

  public void setEmail(String email) {
    this.email = email;
    notifyPropertyChanged(BR.email);
  }

  public User withEmail(String email) {
    this.email = email;
    return this;
  }

  @Bindable
  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
    notifyPropertyChanged(BR.firstName);
  }

  public User withFirstName(String firstName) {
    this.firstName = firstName;
    return this;
  }

  @Bindable
  public String getLastName() {
    return lastName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
    notifyPropertyChanged(BR.lastName);
  }

  public User withLastName(String lastName) {
    this.lastName = lastName;
    return this;
  }

  @Bindable
  public String getAvatar() {
    return avatar;
  }

  public void setAvatar(String avatar) {
    this.avatar = avatar;
    notifyPropertyChanged(BR.avatar);
  }

  public User withAvatar(String avatar) {
    this.avatar = avatar;
    return this;
  }

  public void writeToParcel(Parcel dest, int flags) {
    dest.writeValue(id);
    dest.writeValue(email);
    dest.writeValue(firstName);
    dest.writeValue(lastName);
    dest.writeValue(avatar);
  }

  public int describeContents() {
    return 0;
  }

  public static final DiffUtil.ItemCallback<User> CALLBACK = new DiffUtil.ItemCallback<User>() {
    @Override
    public boolean areItemsTheSame(User oldItem, User newItem) {
      return oldItem.id == newItem.id;
    }

    @Override
    public boolean areContentsTheSame(User oldItem, User newItem) {
      return true;
    }
  };
}

3. Set Up Retrofit Client

As you know retrofit is most commonly used network services in android. We have to set up retrofit client for this app also. Let’s go ahead

3.1 Retrofit Interface

This should be pretty self-explanatory. We are creating service interface named is RestApiService and expose get request methods.

package com.android.paginglibrary.service;

import com.android.paginglibrary.model.UserDBResponse;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;

/**
 * Created by Morris on 03,June,2019
 */
public interface UserDataService {
  @GET("users")
  Call<UserDBResponse> getUsers();

  @GET("users")
  Call<UserDBResponse> getUsersWithPaging(@Query("page") long page);
}

3.2 Retrofit Service Client

Your interface is ready to use, let’s create a web service builder class. To do that create a class named is RetrofitInstance.

package com.android.paginglibrary.service;

import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by Morris on 03,June,2019
 */
public class RetrofitInstance {
  private static Retrofit retrofit = null;
  private static String BASE_URL = "https://reqres.in/api/";

  public static UserDataService getService() {

    if (retrofit == null) {
      retrofit = new Retrofit
          .Builder()
          .baseUrl(BASE_URL)
          .addConverterFactory(GsonConverterFactory.create())
          .build();
    }

    return retrofit.create(UserDataService.class);
  }
}

4. Create a Data Source

Data Source is Incremental data loader for page-keyed content, where requests return keys for next/previous pages. Implement a DataSource using PageKeyedDataSource if you need to use data from page {@code N – 1} to load page {@code N}. This is common, for example, in network APIs that include a next/previous link or key with each page load. In paging library the data source class act as a repository.

In data source we have to override 3 methods.

  • loadInitial – It loads the first page of your data that use to initialize RecyclerView
  • loadBefore – it used when scroll up
  • loadAfter – is called when natural scroll down

That is essential needed for a paged key DataSource

package com.android.paginglibrary.model;

import android.arch.paging.PageKeyedDataSource;
import android.support.annotation.NonNull;
import com.android.paginglibrary.service.RetrofitInstance;
import com.android.paginglibrary.service.UserDataService;
import java.util.ArrayList;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

/**
 * Created by Morris on 03,June,2019
 */
public class UserDataSource extends PageKeyedDataSource<Long, User> {
  private UserDataService userDataService;

  public UserDataSource(UserDataService userDataService) {
    this.userDataService = userDataService;
  }

  @Override
  public void loadInitial(@NonNull LoadInitialParams<Long> params,
      @NonNull final LoadInitialCallback<Long, User> callback) {

    userDataService = RetrofitInstance.getService();
    Call<UserDBResponse> call = userDataService.getUsersWithPaging(1);

    call.enqueue(new Callback<UserDBResponse>() {
      @Override
      public void onResponse(Call<UserDBResponse> call, Response<UserDBResponse> response) {

        UserDBResponse userDBResponse = response.body();
        ArrayList<User> users = new ArrayList<>();

        if (userDBResponse != null &amp;&amp; userDBResponse.getUsers() != null) {
          users = (ArrayList<User>) userDBResponse.getUsers();

          callback.onResult(users, null, (long) 2);
        }
      }

      @Override
      public void onFailure(Call<UserDBResponse> call, Throwable t) {

      }
    });
  }

  @Override
  public void loadBefore(@NonNull LoadParams<Long> params,
      @NonNull LoadCallback<Long, User> callback) {

  }

  @Override
  public void loadAfter(@NonNull final LoadParams<Long> params,
      @NonNull final LoadCallback<Long, User> callback) {

    userDataService = RetrofitInstance.getService();
    Call<UserDBResponse> call = userDataService.getUsersWithPaging(params.key);
    call.enqueue(new Callback<UserDBResponse>() {
      @Override
      public void onResponse(Call<UserDBResponse> call, Response<UserDBResponse> response) {

        UserDBResponse userDBResponse = response.body();
        ArrayList<User> users = new ArrayList<>();

        if (userDBResponse != null &amp;&amp; userDBResponse.getUsers() != null) {
          users = (ArrayList<User>) userDBResponse.getUsers();

          callback.onResult(users, params.key + 1);
        }
      }

      @Override
      public void onFailure(Call<UserDBResponse> call, Throwable t) {

      }
    });
  }
}

5. Create a DataSource.Factory

Using Data Source we need DataSource.Factory which extends DataSource.Factory. Basically it just a factory for DataSources. So first create an instance of data source so that we can use it in our RecyclerView.

package com.android.paginglibrary.model;

import android.arch.lifecycle.MutableLiveData;
import android.arch.paging.DataSource;
import com.android.paginglibrary.service.UserDataService;

/**
 * Created by Morris on 03,June,2019
 */
public class UserDataSourceFactory extends DataSource.Factory {

  private UserDataSource userDataSource;
  private UserDataService userDataService;
  private MutableLiveData<UserDataSource> mutableLiveData;

  public UserDataSourceFactory(UserDataService userDataService) {
    this.userDataService = userDataService;
    mutableLiveData = new MutableLiveData<>();
  }

  @Override
  public DataSource create() {

    userDataSource = new UserDataSource(userDataService);
    mutableLiveData.postValue(userDataSource);
    return userDataSource;
  }

  public MutableLiveData<UserDataSource> getMutableLiveData() {
    return mutableLiveData;
  }
}

As you see here only one method that we override which is create(). However, we need to create a second function here called getMutableLiveData(), which give us back LiveData object.

6. Setup ViewModel

Let’s see the below ViewModel class here’ LivePagedListBuilder<Long, User> ‘ LivePagedListBuilder<Long, User> first argument is page number and is data object.

package com.android.paginglibrary.viewmodel;

import android.app.Application;
import android.arch.lifecycle.AndroidViewModel;
import android.arch.lifecycle.LiveData;
import android.arch.paging.LivePagedListBuilder;
import android.arch.paging.PagedList;
import android.support.annotation.NonNull;
import com.android.paginglibrary.model.User;
import com.android.paginglibrary.model.UserDataSourceFactory;
import com.android.paginglibrary.service.RetrofitInstance;
import com.android.paginglibrary.service.UserDataService;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * Created by Morris on 03,June,2019
 */
public class MainActivityViewModel extends AndroidViewModel {

  private Executor executor;
  private LiveData<PagedList<User>> usersPagedList;

  public MainActivityViewModel(@NonNull Application application) {
    super(application);

    UserDataService userDataService = RetrofitInstance.getService();
    UserDataSourceFactory factory = new UserDataSourceFactory(userDataService);

    PagedList.Config config = (new PagedList.Config.Builder())
        .setEnablePlaceholders(true)
        .setInitialLoadSizeHint(2)
        .setPageSize(4)
        .setPrefetchDistance(4)
        .build();

    executor = Executors.newFixedThreadPool(5);

    usersPagedList = (new LivePagedListBuilder<Long, User>(factory, config))
        .setFetchExecutor(executor)
        .build();
  }

  public LiveData<PagedList<User>> getUserPagedList() {
    return usersPagedList;
  }
}

7. Set up PagedListAdapter

Now we have data ready to load in page by page fashion. We need to create an adapter that accepts this data. In meanwhile do that we need to implement PagedListAdapter. You see this internally extends RecyclerView.Adapter. Basically, PagedListAdapter is a RecyclerView adapter the load’s data into the views piece by piece or page by page. Let’s do that

7.1 Create layout for list item

Simply, create a layout for list item which include ImageView and few TextView like below

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:bind="http://schemas.android.com/apk/res-auto"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    >
  <data>
    <variable
        name="user"
        type="com.android.paginglibrary.model.User"
        />
  </data>
  <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:adjustViewBounds="true"
      >

    <android.support.v7.widget.CardView
        android:id="@+id/cvMovie"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:layout_margin="5dp"
        android:elevation="3dp"
        card_view:cardCornerRadius="1dp"
        >
      <android.support.constraint.ConstraintLayout
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          >
        <ImageView
            android:id="@+id/ivUserProfile"
            android:layout_width="120dp"
            android:layout_height="120dp"
            android:layout_marginBottom="8dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:background="?attr/selectableItemBackgroundBorderless"
            android:scaleType="fitXY"
            bind:layout_constraintBottom_toBottomOf="parent"
            bind:layout_constraintStart_toStartOf="parent"
            bind:layout_constraintTop_toTopOf="parent"
            bind:avatar="@{user.avatar}"
            />

        <TextView
            android:id="@+id/tvName"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_below="@+id/ivUserProfile"
            android:layout_marginEnd="8dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:padding="4dp"
            android:text="@{user.firstName.concat(@string/space).concat(user.lastName)}"
            android:textColor="@color/colorPrimary"
            android:textSize="18sp"
            bind:layout_constraintEnd_toEndOf="parent"
            bind:layout_constraintStart_toEndOf="@+id/ivUserProfile"
            bind:layout_constraintTop_toTopOf="parent"
            tools:text="Morris"
            />

        <TextView
            android:id="@+id/tvEmail"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_below="@+id/tvName"
            android:layout_marginEnd="8dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="4dp"
            android:padding="4dp"
            android:text="@{`Email - ` + user.email}"
            android:textColor="@color/colorAccent"
            android:textSize="16sp"
            bind:layout_constraintEnd_toEndOf="parent"
            bind:layout_constraintStart_toEndOf="@+id/ivUserProfile"
            bind:layout_constraintTop_toBottomOf="@+id/tvName"
            tools:text="morris@gmail.com"
            />

      </android.support.constraint.ConstraintLayout>

    </android.support.v7.widget.CardView>

  </LinearLayout>
</layout>
7.1 Furthermore, create PagedListAdapter

Now I’m creating PagedListAdapter that present data from a PagedList. Basically, It is responsible for presenting data loaded by PagedList and It’s the Implementation of the RecyclerView.Adapter.

package com.android.paginglibrary.adapter;

import android.arch.paging.PagedListAdapter;
import android.content.Context;
import android.content.Intent;
import android.databinding.DataBindingUtil;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.android.paginglibrary.R;
import com.android.paginglibrary.databinding.UserListItemBinding;
import com.android.paginglibrary.model.User;
import com.android.paginglibrary.view.UserActivity;

/**
 * Created by Morris on 03,June,2019
 */
public class UserAdapter extends PagedListAdapter<User, UserAdapter.UserViewHolder> {
  private Context context;

  public UserAdapter(Context context) {
    super(User.CALLBACK);
    this.context = context;
  }

  @NonNull
  @Override
  public UserViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    UserListItemBinding userListItemBinding =
        DataBindingUtil.inflate(LayoutInflater.from(parent.getContext())
            , R.layout.user_list_item, parent, false);

    return new UserViewHolder(userListItemBinding);
  }

  @Override
  public void onBindViewHolder(@NonNull UserViewHolder holder, int position) {

    User user = getItem(position);
    user.setAvatar(user.getAvatar());

    holder.userListItemBinding.setUser(user);
  }

  public class UserViewHolder extends RecyclerView.ViewHolder {
    private UserListItemBinding userListItemBinding;

    public UserViewHolder(@NonNull UserListItemBinding userListItemBinding) {
      super(userListItemBinding.getRoot());
      this.userListItemBinding = userListItemBinding;

      userListItemBinding.getRoot().setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

          int position = getAdapterPosition();

          if (position != RecyclerView.NO_POSITION) {

            User selectedUser = getItem(position);

            Intent intent = new Intent(context, UserActivity.class);
            intent.putExtra("user", selectedUser);
            context.startActivity(intent);
          }
        }
      });
    }
  }
}

8. Add Paging Stuff in MainActivity

So all stuff is ready to use, In MainActivity bind views using data binding. After that we need to set data over RecyclerView. let’s do that

8.1 Add RecyclerView main activity layout file
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    >
  <android.support.v4.widget.SwipeRefreshLayout
      android:id="@+id/swipe_layout"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:padding="8dp"
      >
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="15dp"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        tools:showIn="@layout/activity_main"
        >

      <android.support.v7.widget.RecyclerView
          android:id="@+id/rvMovies"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:clipToPadding="false"
          android:scrollbars="vertical"
          />

    </RelativeLayout>
  </android.support.v4.widget.SwipeRefreshLayout>
</layout>
8.2 Bind layout item to Activity using Data Binding.
  • First of all bind all views using in Activity using DataBinding. After that fetch all user and shows on RecyclerView using below code
package com.android.paginglibrary.view;

import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import android.arch.paging.PagedList;
import android.content.res.Configuration;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import com.android.paginglibrary.R;
import com.android.paginglibrary.adapter.UserAdapter;
import com.android.paginglibrary.databinding.ActivityMainBinding;
import com.android.paginglibrary.model.User;
import com.android.paginglibrary.viewmodel.MainActivityViewModel;

public class MainActivity extends AppCompatActivity {
  private PagedList<User> users;
  private SwipeRefreshLayout swipeRefreshLayout;
  private MainActivityViewModel mainActivityViewModel;
  private ActivityMainBinding activityMainBinding;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
    mainActivityViewModel = ViewModelProviders.of(this).get(MainActivityViewModel.class);

    getUsers();

    swipeRefreshLayout = activityMainBinding.swipeLayout;
    swipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary);
    swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
      @Override
      public void onRefresh() {
        getUsers();
      }
    });
  }

  public void getUsers() {
    mainActivityViewModel.getUserPagedList().observe(this, new Observer<PagedList<User>>() {
      @Override
      public void onChanged(@Nullable PagedList<User> usersFromLiveData) {
        users = usersFromLiveData;
        showOnRecyclerView();
      }
    });
  }

  private void showOnRecyclerView() {
    RecyclerView recyclerView = activityMainBinding.rvMovies;
    UserAdapter userAdapter = new UserAdapter(this);
    userAdapter.submitList(users);
    if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
      recyclerView.setLayoutManager(new GridLayoutManager(this, 1));
    } else {

      recyclerView.setLayoutManager(new GridLayoutManager(this, 2));
    }
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    recyclerView.setAdapter(userAdapter);
    userAdapter.notifyDataSetChanged();
    if (swipeRefreshLayout.isRefreshing()) {
      swipeRefreshLayout.setRefreshing(false);
    }
  }
}

Conclusion

In this android app tutorial, I have leaned implementation of the paging library. I hope it’s helpful for you, then help me by sharing this post with all your friends who learning android app development.

If you have any queries please put your comment below. If you looking to integrate the implementation of the paging library in your android project, Feel free to content us

Read our android architecture components tutorials series

Leave a Reply

avatar
  Subscribe  
Notify of