AndroidTV:ObjectAdapter, Presenter

＊本稿はAndroid L Developer Previewの情報がベース. 正式版で変更される可能性に注意
開発環境: AndroidStudio v0.8.3

Blog: [Yukiの枝折: AndroidTV:ObjectAdapter, Presenter](http://yuki312.blogspot.jp/2014/08/androidtvobjectadapter-presenter.html)

Introduction
--------------------------------------------------
Android leanback support libraryには, メディアコンテンツを閲覧表示するためのAPIが備わっている.  
ここでは`ObjectAdapter`と`Presenter`について記載する.  


Overview
--------------------------------------------------
Android leanback support libraryはコンテンツ(Model)と表示(View)の責務を分離する`Presenter`の仕組みを提供する.  
またModelとPresenterの接続役となる`ObjectAdapter`も提供される.  

ObjectAdapterはデータ(メディアコンテンツ等)と, `PresenterSelector`を内包する抽象クラス.  
BrowserFragment, DetailsFragment(あるいはそれらのサブクラス)の`setAdapter(ObjectAdapter)`でObjectAdapterを登録する.  
PresenterSelectorはModel毎に最適なPresenterを選択し, PresenterがこれをViewにバインドする.  

###Model-View-Presenter Pattern
本稿についてはModel-View-Presenter Patternについて知っておくと理解が早い.  

![enter image description here][1]
[MVP Pattern.]

AndroidTVでは, メディアコンテンツがModelに, PresenterがPresenterに, ViewがViewにそれぞれ対応する.  
ObjectAdapterはModelとPresenterを対応づけるアダプタとして作用する.  


APIs
--------------------------------------------------

###ObjectAdapter
`android.support.v17.leanback.widget.ObjectAdapter`

####Class Overview
> Adapter for leanback activities. Provides access to a data model and is decoupled from the presentation of the items via PresenterSelector.
 
Leanback Activity用のAdapter. Modelへのアクセス手段を提供し, `PresenterSelector`でModelとViewを分離する.  

ObjectAdapterは抽象クラスであり, Modelを管理する手段を提供しない.  
Modelを`ArrayList`で管理する場合はサブクラスの`ArrayObjectAdapter`を使用する.  

```java
// Set Presenter
ArrayObjectAdapter adapter =
        new ArrayObjectAdapter(new MyStringPresenter());

// Add Models
adapter.add("Media Item 1");
adapter.add("Media Item 2");
adapter.add("Media Item 3");
```

ObjectAdapterにPresenterSelectorを設定する主な方法は次の3パターン.  

 1. ObjectAdapterのコンストラクタ引数にPresenterSelectorインスタンスを渡す
 2. ObjectAdapterのコンストラクタ引数にPresenterインスタンスを渡す
 3. ObjectAdapter.setPresenterSelectorメソッドでPresenterSelectorをセットする

```java
// 1. Set Presenter
ArrayObjectAdapter adapter1 = new ArrayObjectAdapter(
        new MyStringPresenter());

// 2. Set PresenterSelector
ArrayObjectAdapter adapter2 = new ArrayObjectAdapter(
        new SinglePresenterSelector(new MyStringPresenter()));

// 3. Lazy initialize
ArrayObjectAdapter adapter3 = new ArrayObjectAdapter();
adapter3.setPresenterSelector(
        new SinglePresenterSelector(new MyStringPresenter()));
```
####Summary
下記は主なAPI.  

ObjectAdapter(PresenterSelector presenterSelector)
: > Construct an adapter with the given PresenterSelector.
: Adapterを初期化し, PresenterSelectorを設定する

ObjectAdapter(Presenter presenter)
: > Construct an adapter that uses the given Presenter for all items. 
: Adapterを初期化し, 全てのリスト項目にPresenterを使用する.内部的には`SinglePresenterSelector`が設定される.

ObjectAdapter.DataObserver
: > A DataObserver can be notified when an ObjectAdapter's underlying data changes. 
: `DataObserver`はObjectAdapterのデータに変更があった場合に通知を受け取ることができる

get(int position)
: > Returns the item for the given position.
: 引数`position`に位置するitem(Model)を返却

getId(int position)
: > Returns id for the given position.
: 引数`position`に位置するidを返却

getPresenter(Object item)
: > Returns the Presenter for the given item from the adapter.
: item(Model)に対応するPresenterを返却

setPresenterSelector(PresenterSelector presenterSelector)
: > Set the presenter selector.
: PresenterSelectorを設定する

---

###PresenterSelector
`android.support.v17.leanback.widget.PresenterSelector`

####Class Overview
> A `PresenterSelector` is used to obtain a Presenter for a given Object.

PresenterSelectorは対象Modelに対応するPresenterを取得するために使用される.  

ObjectAdapterがModelをViewへバインドするためのPresenterの選択に使用される.  
Presenterオブジェクトを取得するために使用される基本的なPresenterSelectorは次の通り.  

 - ClassPresenterSelector
 - SinglePresenterSelector

####Summary
getPresenter(Object item)
: > Returns a presenter for the given item.
: item(Model)に対応するPresenterを返却する.

---

###SinglePresenterSelector
`android.support.v17.leanback.widget.PresenterSelector`
　┗`ndroid.support.v17.leanback.widget.SinglePresenterSelector`  

####Class Overview
常に同じPresenterを返すPresenterSelector. Modelが全て同じタイプである場合に使用する.  

```java
public final class SinglePresenterSelector extends PresenterSelector {
    private final Presenter mPresenter;

    public SinglePresenterSelector(Presenter presenter) {
        mPresenter = presenter;
    }

    @Override
    public Presenter getPresenter(Object item) {
        return mPresenter;
    }
}
```

####Summary
SinglePresenterSelector(Presenter presenter) 
: > The Presenter to return for every item. 
: 全てのModel共通で使用されるPresenterを指定して初期化

getPresenter(Object item)
: > Returns a presenter for the given item. 
: 指定されたitem(Model)に対応するPresenterを返却する. 常に同じPresenterを返却する.

---

###ClassPresenterSelector
`android.support.v17.leanback.widget.PresenterSelector`
　┗`android.support.v17.leanback.widget.ClassPresenterSelector`  

####Class Overview
Modelの内容に基づいてPresenterクラスを切り替えたい場合に使用する.  
ClassPresenterSelectorは`Class`をキーに持つ`Map`でPresenterを管理する.  

```java
public final class ClassPresenterSelector extends PresenterSelector {
    private final HashMap<Class<?>, Presenter> mClassMap = new HashMap<Class<?>, Presenter>();

    public void addClassPresenter(Class<?> cls, Presenter presenter) {
        mClassMap.put(cls, presenter);
    }

    @Override
    public Presenter getPresenter(Object item) {
        // item.getClass() にマッチするPresenterをmClassMapから見つけ出し返却する
    }
}
```

####Summary
addClassPresenter(Class<?> cls, Presenter presenter)
: > (no description)
: Modelの型に対応するPresenterを登録する

getPresenter(Object item)
: > Returns a presenter for the given item. 
: 指定されたitem(Model)に対応するPresenterを返却する.

---

###Presenter
`android.support.v17.leanback.widget.Presenter`

####Class Overview
> A Presenter is used to generate Views and bind Objects to them on demand. It is closely related to concept of an RecyclerView.Adapter, but is not position-based. 

PresenterはViewを生成しObjectをバインドする.
これは`Recyclerview.Adapter`のコンセプトと近似しているがpositionベースではない.  

> A trivial Presenter that takes a string and renders it into a TextView: 

下記はPresenterが`String`を受け取りそれを`TextView`にレンダリングするコード:

```java
public class StringTextViewPresenter extends Presenter {
    // This class does not need a custom ViewHolder, since it does not use
    // a complex layout.
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent) {
        return new ViewHolder(new TextView(parent.getContext()));
    }
    
    @Override
    public void onBindViewHolder(ViewHolder viewHolder, Object item) {
        String str = (String) item;
        TextView textView = (TextView) viewHolder.mView;
        textView.setText(item);
    }
    
    @Override
    public void onUnbindViewHolder(ViewHolder viewHolder) {
        // Nothing to unbind for TextView, but if this viewHolder had
        // allocated bitmaps, they can be released here.
    }
}
```

####Summary
主なAPIは下記.

onBindViewHolder(Presenter.ViewHolder viewHolder, Object item)
: > Binds a View to an item.
: item(Model)を`View`にバインドする

onCreateViewHolder(ViewGroup parent)
: > Creates a new View.
: 新しいViewを作成する

onUnbindViewHolder(Presenter.ViewHolder viewHolder)
: > Unbinds a View from an item. Any expensive references may be released here, and any fields that are not bound for every item should be cleared here. 
: Viewからitem(Model)をアンバインドする. Viewにバインドされていないものも含め強参照はここでリリースされるべき.

---

###Presenter.ViewHolder
`android.support.v17.leanback.widget.Presenter.ViewHolder`

####Class Overview
> ViewHolder can be subclassed and used to cache any view accessors needed to improve binding performance (for example, results of findViewById) without needing to subclass a View.

`ViewHolder`はサブクラス化することができる.(その他は一般的なViewHolderと同じ)

####Summary
特記事項なし

---

> **License:**
>Portions of this page are modifications based on work created and [shared by the Android Open Source Project](http://code.google.com/policies.html)
 and used according to terms described in the [Creative Commons 2.5 Attribution License](http://creativecommons.org/licenses/by/2.5/).  
  
> "Model View Presenter GUI Design Pattern" by Google  
>  http://www.gwtproject.org/articles/testing_methodologies_using_gwt.html
>  Licensed under Creative Commons   Attribution-Share Alike 3.0 via Wikimedia Commons -  
> http://commons.wikimedia.org/wiki/File:Model_View_Presenter_GUI_Design_Pattern.png#mediaviewer/File:Model_View_Presenter_GUI_Design_Pattern.png


  [1]: https://lh4.googleusercontent.com/-hiIDQZ-CLtI/U-wrpTU6esI/AAAAAAAAEkc/H-nS_eGf89Q/s600/Model_View_Presenter_GUI_Design_Pattern.png "Model_View_Presenter_GUI_Design_Pattern.png"