Android. Recycler With Cards, and Their Friend Infinite Scroll.
Mobile Apps Development A-Z Guide.
Give us a message if you’re interested in Blockchain and FinTech software development or just say Hi at Pharos Production Inc.
Model.
Let’s define a model we’re going to fetch. For the sake of simplicity, we will use just two fields — identifier and details. Both are plain strings. Here we also define @SerializedName annotations to automagically decode it from incoming JSON using the gson library. Also, we need getters for both values and overridden toString() method to print the content if required. If you don’t know why every variable here has m suffix — because it means a member of a class variable.
Fragment
Next, let’s define a fragment with recycler view in it. I’m using recyclers inside fragments on my current project, but it will be the same if you’re going to use it in activities.
Let’s define just one constant:
- LOG_TAG — just a simple log title to get a clue who is logging this or that message.
Variables:
- mRecyclerView — bound to a layout’s recyclerView element recycler. I prefer to use ButterKnife library to simplify connection of all UI variables to their views.
- mAdapter — recycler adapter object of type RequestsRecyclerAdapter. It extends RecyclerView.Adapter class.
- mLayoutManager — layout manager, it manages an on-screen representation of the recycler.
- isLoading — recycler action state. It halts any additional actions sent to a recycler if data is loading.
- apiPage — this object contains a current page, total pages, batch size, and total entries. All this data supported by the server in every response. We will look through this class later.
Because we’re in a fragment context, we define two lifecycle methods.
- onCreate — we start to fetch the first page of data here before app expands its layout from XML.
- 0nCreateView — we load all UI components we need here.
First, we inflating a required layout and bind all member variables — mRecyclerView here.
We need to define the adapter which will handle all server-model operations. Also, we need a layout manager with passing in a context and a span count.
Now we’re ready to set up our recycler view:
- Layout manager — for a layout.
- Adapter — for a data.
- Item Animator — for items appearance.
- Has fixed size property —for a performance.
- Item decoration — for a grid visual properties like cell padding etc.
- Scroll listener — this object will listen to scroll events and trigger adapter if a new page is required.
We define only one public method to create a fragment object. It should take all initial parameters, but we don’t have any for now.
Now let’s define data loading method. It’s not the best idea to define such methods in a fragment instead of an adapter or somewhere else in a place more related to data rather than to UI. But this is my own prefs and we will do it this way for now.
First, we check if there is the next page at all. No sense to trigger the server if there is nothing to trigger. Remember, we’re using automated triggering via scroll list position. So we query the server to get all requests. We pass 3 parameters — current activity to show error messages to the user if any, current page and a response anonymous function. If server responding with a success, we receiver a new state for a current page — new page number, new page size(usually it’s a constant), new total entries number and a new total pages calculated from page size and total entries. Then we add all new data to the adapter and perform adapter update the UI via notifyDataSetChanged() method.
There are two boilerplate classes we should define to support decorator and scroll listener. Java is full of enterprise-friendly boilerplates.
The first class is a Scroll Listener. We should define yet another boilerplate required method — onScrollStateChaged. And more useful method — onScrolled. All our automation triggering logic is in onScrolled.
All we need to do here is to check if the app is not loading something here and if a new page is in a range of total pages number responded by the server previously. If we succeed with these two requirements, then app calls loadData method defined above.
Another class is a decorator which will prepare a nice layout. There is nothing to explain here, this is just a helper class.
Recycler Layout
A layout is super-simple. Here we define only linear layout as a container and recycler view with a couple of standard properties. The only thing I should mention is a tools:listitem property — that’s to visually display how the layout is looking just inside the interface builder. The card layout is simple too. According to our model, we have just one element here — TextView. That’s all. CardView by itself is a subclass of Frame Layout. All its properties have self-explanatory meaning.
Adapter.
The most interesting part of our story is the adapter. It’s a subclass of a RecyclerView.Adapter. We define log constant and a member variable for all fetched requests as a SortedList.
We define only one lifecycle method here. But it will have tons of boilerplate inside! We compare items by their identifier for now. But surely you can use more properties.
A couple of more adapter methods. We should define even more boilerplate methods! OnCreateViewHolder — we define a ViewHolder class. This is a battle-tested pattern in Android development to reuse cells instead of creating of them every time you need to display a new cell. OnBindViewHolder — the app will invoke this method when recycler is going to reuse a holder. We define a bunch of properties here and an entity to show. GetItemCount is another required method to provide a total number of items to the recycler.
Now let’s define several useful methods to add, remove and get our requests. We will not use them for now, but it’s a good idea to define a full suite of operations here. All of them do something useful with requests set. Also, they can trigger an update of the recycler via begin-end Batched Updates like in addAll method.
The last one piece in a puzzle is a ViewHolder. It’s an inner class of the adapter here. It’s a child of RecyclerView.ViewHolder class and also it implements click listener — we want to react somehow if the user taps on a request view.
Here we bind a layout to a holder and add onClickListener to the root view. Also, we have one setter to set an entity.
Thanks for reading!