Developing for the Living Room: How to Build an Android App for Fire TV (Part 4)

WORKING WITH THE PRESENTER CLASS

In the previous episode of this series we discussed how to create the main interface of our Leanback-enabled project through the BrowseFragment. Now let’s take a closer look into the Presenter class. The Presenter class allows us to define the look and feel of our Leanback-enabled app without editing the underlying data structure.

The Presenter Class

The Leanback template we created was built following a custom version of the common development pattern, Model-view-controller (MVC), in which the Presenter class acts as the View. The Presenters are passed to the ArrayObjectAdapter as arguments and define how the content of the Adapter should be displayed

The Leanback approach provides a variety of predefined Presenters:

  • CardPresenter defines the UI of a single item displayed within the row Adapter
  • ListRowPresenter defines how various content in a row should be displayed and arranged
  • DetailsDescriptionPresenter defines the UI of the DetailsFragment

Implementing the Presenters are quite similar: they all follow the ViewHolder pattern and are mostly composed by Custom Views with methods to set the fields of the views. Let’s take a close look at the customizing the CardPresenter as an example:

Customizing the CardPresenter

In the BrowseFragment, we see that the CardPresenter defines the UI of a single item of the adapter.

public class MainFragment extends BrowseFragment { 
CardPresenter cardPresenter = new CardPresenter(); 
//Create the adapter for the row and add all the movies ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);

The highlighted view in the previous image is a custom view called ImageCardView and is used in the CardPresenter to define the UI of a single component.

Let’s analyze how views are initialized in the CardPresenter.

public class CardPresenter extends Presenter { 
public ViewHolder onCreateViewHolder(ViewGroup parent) {
...
ImageCardView cardView = new ImageCardView(parent.getContext); cardView.setFocusable(true);
cardView.setFocusableInTouchMode(true);
return new ViewHolder(cardView);
... }

There are two things to notice here:

  1. As we mentioned before, the CardPresenter is built on the ViewHolder pattern. This ensures views are correctly recycled and memory is not wasted.
  2. The CardView is set to SetFocusable(true) and setFocusableInTouchMode(true). Although there is no existing touch interaction on a TV screen, this step is necessary because this is how Android currently manages the focus-ability of views.

Now let’s take a look at how the components of the ImageCardView (and of the Presenter) are set:

public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) { 
Movie movie = (Movie) item; 
ImageCardView cardView = (ImageCardView) viewHolder.view; 
if (movie.getCardImageUrl() != null) {
  cardView.setTitleText(movie.getTitle());
cardView.setContentText(movie.getDescription());
Glide.with(viewHolder.view.getContext())
.load(movie.getCardImageUrl())
.centerCrop()
.into(cardView.getMainImageView());
}
}

In this example we use our own custom class “Movie” to retrieve the information we want to display.

The cardView is retrieved from the ViewHolder, then we have the simple setters setTitleText() and setContentText(), to edit the main fields of the view.

To retrieve the image for the thumbnail, Leanback automatically uses the Glide library (but you can easily replace it with the image loading library of your choice).

Up next:

In the next episode of this series we’ll make a further step towards fully understanding how a Leanback-enabled project works, moving to the second step of the user journey: building and displaying the details of specific content using the DetailsFragment.

Stay tuned!

Mario Viviani (@mariuxtheone)


Originally published at developer.amazon.com.