AndroidでParse入門 - User Interface -
元ネタ
こちらを参考にUser Interfaceについてまとめます。
https://parse.com/docs/android_guide#ui
User Interface
アプリケーションのユーザはAndroidのUIコンポーネントと対話します。ParseはParse上のデータを効率よく扱うための共通的なUIウィジェットのサブクラスを提供しています。
ParseQueryAdapter
Parseはコレクションデータを表示するためにAdapterの実装クラスを提供しています。静的なオブジェクト配列を使うベーシックなListAdapterを使う代わりに、ParseQueryAdapterクラスを使えば抽象的なレイヤーが提供されます。その結果、AdapterView(たとえばListView、GridView)を使って、Parseクラスのデータを簡単に表示できるようになります。
Activity上でデータを表示するためのParseQueryAdapterの使い方は、onCreateメソッドで次のように実装します。
- ParseQueryAdapterを生成します。
- 必要に応じてカスタマイズします(データの問い合わせ、ビューの変更などの詳細については、後のセクションを参照してください)
- setAdapter()メソッドによってAdapterViewにAdapterをセットします。
WindowにAdapterViewがアタッチされると、ParseQueryAdapterは自動的にデータの先頭部分をフェッチします。このサブクラスは次に示すコードを簡略化します。
- タップで次のページを読み込むページネーション
- 行内のリモートイメージの表示やダウンロードの設定
- Parseオブジェクト配列の自動読み込み管理
- データライフサイクルにおける主要なイベントからのコールバック
次のコードは、ListViewにデータを表示するためのシンプルなParseQueryAdapterのセットアップです。わずかな設定で機能的なListViewが実装できます。
// Inside an Activity public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Uses a layout with a ListView (id: "listview"), which uses our Adapter. setContentView(R.layout.main); ParseQueryAdapter<ParseObject> adapter = new ParseQueryAdapter<ParseObject>(this, "Instrument"); adapter.setTextKey("name"); adapter.setImageKey("photo"); ListView listView = (ListView) findViewById(R.id.listview); listView.setAdapter(adapter); }
このビューはInstrumentsリストのnameを表示します。ここでは記述していないコードに注目してください。連続したページのフェッチロジックを記述していませんし、配列データの管理ロジックも記述していません。UIウィジェットに表示するイメージをバックグラウンドでダウンロードするコードもないですし、次のページをロードするタッチイベントの処理も記述していません。
ParseQueryAdapterは、データの加工や表示方法、フェッチ時の前処理、後処理をカスタマイズできます。以降の節では、ParseQueryAdapterを使ってあなたが何をできるのかを解説します。ニーズに合わせるために、どのように微調整すれば良いかを見ていきましょう。
Customizing the Query
ParseQueryAdapterのコンストラクタは、ContextとParseのクラス名を引数に取ります。これにより、クラスに属するすべてのParseObjectがフェッチされ、createdAtタイムスタンプ順に表示されます。
Parseは、この振る舞いを変更できるようにArrayAdapterの機能から設計しています。ParseQueryAdapterは、Adapterによって表示されるオブジェクト配列を設定するのではなく、自分で定義したParseQueryを返すQueryFactoryクラスを引数に受け取ります。QueryFactoryインスタンスをコンストラクタで受け取ることで、Adapterはクエリの結果を使用し、オブジェクトをフェッチして表示するようになります。
次のコードは、punkとmetalで4名以上メンバーがいるバンドをレコードの売上順で表示するためのParseQueryAdapterのセットアップです。
ParseQueryAdapter<ParseObject> adapter = new ParseQueryAdapter<ParseObject>(this, new ParseQueryAdapter.QueryFactory<ParseObject>() { public ParseQuery<ParseObject> create() { // Here we can configure a ParseQuery to our heart's desire. ParseQuery query = new ParseQuery("Band"); query.whereContainedIn("genre", Arrays.asList({ "Punk", "Metal" })); query.whereGreaterThanOrEqualTo("memberCount", 4); query.orderByDescending("albumsSoldCount"); return query; } });
Customizing the Rows
AdapterView内の個々ビューのデフォルトレイアウトは、ParseImageViewとTextViewによるシンプルなLinearLayoutです。ParseQueryAdapterに対してsetTextKey(String) を呼び出すと、指定したキーがParseObjectの表示項目となり、TextViewに表示されます。同様に、setImageKey(String)を呼び出すと、指定したキーがParseObjectの表示項目となり、ImageViewに表示されます。
行をカスタマイズする一つの方法は、getItemView(ParseObject, View, ViewGroup) やgetNextPageView(View, ViewGroup)をオーバーライドし、スーパークラスの適切なメソッドを呼び出す方法です。独自のレイアウトをスーパークラスの実装に提供する場合、getItemView(ParseObject, View, ViewGroup) とgetNextPageView(View, ViewGroup) は、textKeyがセットされているならTextView (id: android.R.id.text1)、imageKeyがセットされているならParseImageView (id: android.R.id.icon)を期待します。*1
独自のレイアウトをinflateして設定し、TextViewとParseImageView、さらに"description"TextView(id: R.id.description)を追加する場合、次のようになります。
@Override public View getItemView(ParseObject object, View v, ViewGroup parent) { if (v == null) { v = View.inflate(getContext(), R.layout.adapter_item, null); } // Take advantage of ParseQueryAdapter's getItemView logic for // populating the main TextView/ImageView. // The IDs in your custom layout must match what ParseQueryAdapter expects // if it will be populating a TextView or ImageView for you. super.getItemView(object, v, parent); // Do additional configuration before returning the View. TextView descriptionView = (TextView) v.findViewById(R.id.description); descriptionView.setText(object.getString("description")); return v; }
行をカスタマイズするもう一つの方法は、ParseQueryAdapterのメソッドをオーバーライドし、スーパークラスの実装を完全に無視する方法です。ParseObjectに定義されたcolorを個々のItem Viewに適用するシンプルな例は次のようになります。
@Override public View getItemView(ParseObject object, View v, ViewGroup parent) { if (v == null) { v = View.inflate(getContext(), R.layout.adapter_item, null); } v.setBackgroundColor(object.getInt("color")); return v; } @Override public View getNextPageView(View v, ViewGroup parent) { if (v == null) { // R.layout.adapter_next_page contains an ImageView with a custom graphic // and a TextView. v = View.inflate(getContext(), R.layout.adapter_next_page, null); } TextView textView = (TextView) v.findViewById(R.id.nextPageTextViewId); textView.setText("Loaded " + getCount() + " rows. Get more!"); return v; }
Loading Remote Images in Rows
ParseQueryAdapterは、簡単にリモートイメージを表示することができます。setImageKey(String)を呼び出せば、ParseFileを保持したParseObjectのキー名を通じて、Parseからイメージをフェッチし対象行のParseImageViewにロードします。
イメージは非同期でダウンロードされるので、ParseImageViewはバックグラウンドで更新されます。ユーザのスクロールにより、Adapterによって行がリサイクルされると、ParseObjectが割り当てられ、イメージがフェッチされて表示されます。
画像のフェッチが完了するまでプレースホルダイメージを定義することもできます。ParseQueryAdapterのsetPlaceholder(Drawable) を呼び出すと、指定したDrawableがフォールバックイメージとして描画されます。
Lifecycle Methods
カスタムロジックを適用するために、Adapterに2つのデータライフサイクルフックを用意しています。一つは、データのクエリの前処理であり、もう一つはクエリからフェッチされたオブジェクトがロードされたときの後処理です。これらのメソッドは、ロードされたUIの切り替えなどに有効です。OnQueryLoadListenerはsetOnQueryLoadListenerによってセットします。onLoading() とonLoaded(List, Exception) を実装する必要があります。
Pagination
ページネーションは、テーブルからリストの1ページ目だけを取得します。ページに含むオブジェクトの件数は、setObjectsPerPage(int)を呼び出すことで指定できます。
クエリはページネーションによって自動的に調整されます。AdapterViewの最終行にページネーション行が表示されるので、ユーザは次のページを読み込むことができます。
ページネーションはデフォルトで有効となっています。無効にしたい場合はsetPaginationEnabled(false)を呼び出してください。ページネーションを無効にすると、ParseQueryAdapterはデフォルトで最大100件の結果を読み込みます。
Auto-loading of Data
ParseQueryAdapterを設定したAdapterViewがWindowにアタッチされると、先頭のページをフェッチする際にParseQueryAdapterのloadObjects()メソッドが呼び出されます。この挙動を無効にしたい場合(データの読み込みを遅延させたり、カスタムロジックを実行させたりしたい場合)、setAutoload(false)を呼び出してください。その場合、loadObjects()は手動で呼び出すようにします。
*1:変な言い回しですみません、後のコード見た方が良いです。