Displaying Lists with Recycle View Chapter 8 What

  • Slides: 32
Download presentation
Displaying Lists with Recycle View Chapter 8

Displaying Lists with Recycle View Chapter 8

What are we covering? • Criminal. Intent’s model layer currently consists of a single

What are we covering? • Criminal. Intent’s model layer currently consists of a single instance of Crime. In this chapter, you will update Criminal. Intent to work with a list of crimes. The list will display each Crime’s title and date. • Lets run app and see

Crime Lab Object • In the model layer, you have a new object, Crime.

Crime Lab Object • In the model layer, you have a new object, Crime. Lab, that will be a centralized data stash that stores Crime objects. • Displaying a list of crimes requires a new activity and a new fragment in Criminal. Intent’s controller layer: Crime. List. Activity and Crime. List. Fragment.

MVC

MVC

MVC Cont’d • In the model layer, you have a new object, Crime. Lab,

MVC Cont’d • In the model layer, you have a new object, Crime. Lab, that will be a centralized data stash for Crime objects. • Displaying a list of crimes requires a new activity and a new fragment in Criminal. Intent’s controller layer: Crime. List. Activity and Crime. List. Fragment. • Crime. Activity and Crimea. Fragment are for details and not used in Chapter 9. • the view objects associated with Crime. List. Activity and Crime. List. Fragment. The activity’s view will consist of a fragment-containing Frame. Layout. The fragment’s view will consist of a Recycler. View.

Updating Criminal. Intent’s Model Layer • You are going to store the list of

Updating Criminal. Intent’s Model Layer • You are going to store the list of crimes in a singleton. • A singleton is a class that allows only one instance of itself to be created. • A singleton exists as long as the application stays in memory, so storing the list in a singleton will keep the crime data available no matter what happens with activities, fragments, and their lifecycles. • Note , that with singleton classes, as they will be destroyed when Android removes your application from memory.

Singletons and Centralized Storage • To create a singleton, you create a class with

Singletons and Centralized Storage • To create a singleton, you create a class with a private constructor (static)and a get() method that returns the instance. • If the instance already exists, then get() simply returns the instance. If the instance does not exist yet, then get() will call the constructor to create it.

Singletons Con’t • The Crime. Lab constructor requires a Context parameter. This is common

Singletons Con’t • The Crime. Lab constructor requires a Context parameter. This is common in Android; • Having a Context parameter allows the singleton to start activities, access project resources, find your application’s private storage, and more. • Notice in get(Context) that you do not directly pass in the Context parameter to the constructor. This Context could be an Activity or another Context object, like Service. • You cannot be sure that just any Context will exist as long as Crime. Lab needs it, which is for the life of the application.

What is a Context? • Its the context of current state of the application/object.

What is a Context? • Its the context of current state of the application/object. • It lets newly created objects understand what has been going on. • Typically you call it to get information regarding another part of your program (activity, package/application) • The application context is a Context that is global to your application.

Array. List • List < E > is an interface that supports an ordered

Array. List • List < E > is an interface that supports an ordered list of objects of a given type. It defines methods for retrieving, adding, and deleting elements. • A commonly used implementation of List is Array. List, which uses a regular Java array to store the list elements. • Crime. Lab. java • m. Crimes = new Array. List < >(); .

Abstract Activity for Hosting Fragment • activity_crime. xml is already generic <? xml version

Abstract Activity for Hosting Fragment • activity_crime. xml is already generic <? xml version =" 1. 0" encoding =" utf-8"? > < Frame. Layout xmlns: android =" http: // schemas. android. com/ apk/ res/ android" android: id ="@ + id/ fragment_container" android: layout_width =" match_parent" android: layout_height =" match_parent" /> • Because activity_crime. xml does not name a particular fragment, you can use it for any activity hosting a single fragment. Rename it activity_fragment. xml to reflect its larger scope.

An abstract Activity class • To create the Crime. List. Activity class, you could

An abstract Activity class • To create the Crime. List. Activity class, you could reuse Crime. Activity’s code.

Creating the new controllers • Now, you will create the two new controller classes:

Creating the new controllers • Now, you will create the two new controller classes: Crime. List. Activity and Crime. List. Fragment. • Modify the new Crime. List. Activity class to also subclass Single. Fragment. Activity and implement the create. Fragment() method.

Declaring Crime. List. Activity • If you have other methods in your Crime. List.

Declaring Crime. List. Activity • If you have other methods in your Crime. List. Activity, such as on. Create, remove them. Let Single. Fragment. Activity do its job and keep Crime. List. Activity simple. • Declaring Crime. List. Activity as the launcher activity (Android. Manifest. xml)

Recycler. View, Adapter, and View. Holder • Now, you want Crime. List. Fragment to

Recycler. View, Adapter, and View. Holder • Now, you want Crime. List. Fragment to display a list of crimes to the user. To do this, you will use a Recycler. View. • Recycler. View is a subclass of View. Group. It displays a list of child View objects, one for each item in your list of items. Depending on the complexity of what you need to display, these child Views can be complex or very simple. For your first implementation, each item in the list will display the title and date of a Crime. The View object on each row will be a Linear. Layout containing two Text. Views,

Recycler. View

Recycler. View

View Holders and Adapters • The Recycler. View’s only responsibilities are recycling Text. Views

View Holders and Adapters • The Recycler. View’s only responsibilities are recycling Text. Views and positioning them onscreen. • To get the Text. Views in the first place, it works with two classes that you will build in a moment: an Adapter subclass and a View. Holder subclass.

View. Holders • View. Holder does one thing: It holds on to a View

View. Holders • View. Holder does one thing: It holds on to a View • item. View, a field that your superclass Recycler. View. Holder assigns for you. The item. View field is your View. Holder’s reason for existing: It holds a reference to the entire View you passed into super( view).

Adapters • Recycler. View does not create View. Holders itself. Instead, it asks an

Adapters • Recycler. View does not create View. Holders itself. Instead, it asks an adapter. • An adapter is a controller object that sits between the Recycler. View and the data set that the Recycler. View should display. • The adapter is responsible for: creating the necessary View. Holders binding View. Holders to data from the model layer. • When the Recycler. View needs a view object to display, it will have a conversation with its adapter.

Recycler. View Adapter • First, the Recycler. View asks how many objects are in

Recycler. View Adapter • First, the Recycler. View asks how many objects are in the list by calling the adapter’s get. Item. Count() method. . Then the Recycler. View calls the adapter’s on. Create. View. Holder( View. Group, int) method to create a new View. Holder, along with its juicy payload: a View to display. • Finally, the Recycler. View calls on. Bind. View. Holder( View. Holder, int). The Recycler. View will pass a View. Holder into this method along with the position. The adapter will look up the model data for that position and bind it to the View. Holder’s View. • To bind it, the adapter fills in the View to reflect the data in the model object. Once enough View. Holders have been created, Recycler. View stops calling on. Create. View. Holder(…). Instead, it saves time and memory by recycling old View. Holders. •

Using a Recycler View • Adding the Recycler. View dependency • Your Recycler. View

Using a Recycler View • Adding the Recycler. View dependency • Your Recycler. View will live in Crime. List. Fragment’s layout file. First, you must create the layout file.

Recycler. View to a layout file (fragment_crime_list. xml)

Recycler. View to a layout file (fragment_crime_list. xml)

Recycler. View Cont • Note that as soon as you create your Recycler. View,

Recycler. View Cont • Note that as soon as you create your Recycler. View, you give it another object called a Layout. Manager. • Recycler. View requires a Layout. Manager to work. If you forget to give it one, it will crash. • on. Create. View. Holder is called by the Recycler. View when it needs a new View. Holder to display an item with. • In this method, you create a Layout. Inflater and use it to construct a new Crime. Holder.

Binding List Items • Binding is taking Java code (like model data in a

Binding List Items • Binding is taking Java code (like model data in a Crime, or click listeners) and hooking it up to a widget. • All the code that will do the real work of binding will go inside your Crime. Holder. That work starts with pulling out all the widgets you are interested in. This only needs to happen one time, so write this code in your constructor. • Your Crime. Holder will also need a bind( Crime) method. This will be called each time a new Crime should be displayed in your Crime. Holder.

Bind() • private class Crime. Holder extends Recycler. View. Holder implements View. On. Click.

Bind() • private class Crime. Holder extends Recycler. View. Holder implements View. On. Click. Listener { private Crime m. Crime; private Text. View m. Title. Text. View; private Text. View m. Date. Text. View; public Crime. Holder(Layout. Inflater inflater, View. Group parent) { super(inflater. inflate(R. layout. list_item_crime, parent, false)); item. View. set. On. Click. Listener(this); } m. Title. Text. View = (Text. View) item. View. find. View. By. Id(R. id. crime_title); m. Date. Text. View = (Text. View) item. View. find. View. By. Id(R. id. crime_date); public void bind(Crime crime) { m. Crime = crime; m. Title. Text. View. set. Text(m. Crime. get. Title()); m. Date. Text. View. set. Text(m. Crime. get. Date(). to. String()); }

Calling bind() • (inside of ) private class Crime. Adapter extends Recycler. View. Adapter<Crime.

Calling bind() • (inside of ) private class Crime. Adapter extends Recycler. View. Adapter<Crime. Holder> { • @Override public void on. Bind. View. Holder(Crime. Holder holder, int position) { Crime crime = m. Crimes. get(position); holder. bind(crime); }

Responding to Presses • Handling touch events is mostly up to you. If you

Responding to Presses • Handling touch events is mostly up to you. If you need them, Recycler. View can forward along raw touch events. • Instead, you can handle them like you normally do: by setting an On. Click. Listener. Since each View has an associated View. Holder, you can make your View. Holder the On. Click. Listener for its View.

Responding to Presses

Responding to Presses