アンドロイド - 推定所要時間: 25分
このチュートリアルでThorben Primkeは、RealmRecyclerViewというRealmとRecyclerViewを組み合わせて使うことに特化したUIコンポーネントを使用して、Realmに格納されたデータをグリッド表示する方法を示します。
アプリケーションにグリッドレイアウトを実装しようとしたことはありませんか?データがRealmに格納されているなら、すぐにこのようなインタフェースを作成することができます。一番の売りは、データを更新するだけでアニメーションと共に自動的に表示が更新されるところです。
それでは始めてみましょう。もし先に完成版を見たい場合は、GitHub上に置いてあります。 ここをクリック
完成すると以下のようなものができあがります。
チュートリアル
ニューヨーク・タイムズのAPIからデータを取得するためにはAPIキーが必要です。ニューヨーク・タイムズ開発者サイトから無料のAPIキーを取得してください。
“Empty Activity”テンプレートを使用して新しいAndroid Studioプロジェクトを作成します。
次に、プロジェクトにRealmSearchViewを追加します。RealmSearchViewはjitpack.ioリポジトリからGradleの依存ライブラリとして利用可能です。
リポジトリ追加するには、プロジェクトのプロジェクトのルートにあるbuild.gradle
に次の行を追加します。
maven { url "https://jitpack.io" }
追加を行うと、build.gradle
は次のようになります。
allprojects {
repositories {
jcenter()
maven { url "https://jitpack.io" }
}
}
次に、app
モジュールのbuild.gradle
ファイルに次の行を追加します。
compile 'com.github.thorbenprimke:realm-recycler-view:0.9.4'
このチュートリアルでは、サンプルデータセットと画像読み込みライブラリを使用します。これらをアプリケーションに追加するためにapp
モジュールのbuild.gradle
ファイルに次の行を追加します。
compile 'com.github.thorbenprimke:realm-nytimes-data:0.9.2'
compile 'com.github.bumptech.glide:glide:3.6.1'
以上で準備は完了です。再同期(Sync Project with Gradle files)を行い、次に進んでください。
統合
これでベースとなるプロジェクトのセットアップが完了したことになります。それではアプリケーションにRealmRecyclerView
を組み込み、表示をカスタマイズするためにRealmBasedRecyclerViewAdapter
のサブクラスを作成しましょう。
MainActivity
のレイアウトファイルを開き、以下のように内容を置き換えます。
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<co.moonmonkeylabs.realmrecyclerview.RealmRecyclerView
android:id="@+id/realm_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:rrvIsRefreshable="false"
app:rrvLayoutType="Grid"
app:rrvGridLayoutSpanCount="2"
/>
</FrameLayout>
以下の3つのカスタム属性を指定している点に注意してください。
- rrvIsRefreshable - これはRecyclerViewの引っ張って更新(pull to refresh)の機能を無効にします。
-
rrvLayoutType -
RealmRecyclerView
はさまざまなレイアウトタイプをサポートしており、このチュートリアルでは、2列の「グリッド」を指定します。 - rrvGridLayoutSpanCount - この属性は’rrvLayoutType’がグリッドに設定されている場合、列数を設定する必要があります。
サンプルデータに、NYTimesStory
(ソース)クラがあります。このクラスをストーリーを表示するためのアダプラーのデータ型として使用します。
NYTimesStory
は、ビューを用いて以下のように表示されます。
_------------------_
Image
Date
Title
Abstract
_------------------_
RealmBasedRecyclerViewAdapter
のViewHolderで使用されるレイアウトはgrid_item_view.xml
という名前です。layout
フォルダの中に以下の内容のlayout xmlファイルを作成してください。
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<ImageView
android:id="@+id/image"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginTop="5dp"
android:layout_gravity="center_horizontal"/>
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:singleLine="true"
android:ellipsize="end"
android:textStyle="bold"/>
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_gravity="center_horizontal"
android:singleLine="true"
android:ellipsize="end"/>
<TextView
android:id="@+id/story_abstract"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:gravity="center_horizontal"
android:maxLines="5"
android:ellipsize="end"/>
</LinearLayout>
データモデルは、画面にNYTimesStory
を表示するために、上記のレイアウトにマッピングされます。
データモデルとそれがどのように画面に表示されるかを理解したので、RealmBasedRecyclerViewAdapter
クラスのサブクラスを実装します。
public class NYTimesStoryRecyclerViewAdapter extends RealmBasedRecyclerViewAdapter<NYTimesStory,
NYTimesStoryRecyclerViewAdapter.ViewHolder> {
public NYTimesStoryRecyclerViewAdapter(
Context context,
RealmResults<NYTimesStory> realmResults,
boolean automaticUpdate,
boolean animateIdType) {
super(context, realmResults, automaticUpdate, animateIdType);
}
public class ViewHolder extends RealmViewHolder {
public TextView title;
public TextView publishedDate;
public ImageView image;
public TextView storyAbstract;
public ViewHolder(LinearLayout container) {
super(container);
this.title = (TextView) container.findViewById(R.id.title);
this.publishedDate = (TextView) container.findViewById(R.id.date);
this.image = (ImageView) container.findViewById(R.id.image);
this.storyAbstract = (TextView) container.findViewById(R.id.story_abstract);
}
}
@Override
public ViewHolder onCreateRealmViewHolder(ViewGroup viewGroup, int viewType) {
View v = inflater.inflate(R.layout.grid_item_view, viewGroup, false);
ViewHolder vh = new ViewHolder((LinearLayout) v);
return vh;
}
@Override
public void onBindRealmViewHolder(ViewHolder viewHolder, int position) {
final NYTimesStory nyTimesStory = realmResults.get(position);
viewHolder.title.setText(nyTimesStory.getTitle());
viewHolder.publishedDate.setText(nyTimesStory.getPublishedDate());
final RealmList<NYTimesMultimedium> multimedia = nyTimesStory.getMultimedia();
if (multimedia != null && !multimedia.isEmpty()) {
Glide.with(GridExampleActivity.this).load(
multimedia.get(0).getUrl()).into(viewHolder.image);
} else {
viewHolder.image.setImageResource(R.drawable.nytimes_logo);
}
viewHolder.storyAbstract.setText(nyTimesStory.getStoryAbstract());
}
}
onCreateRealmViewHolder
メソッドはgrid_item_view
レイアウトをインフレートしViewHolder
に引き渡します。
onBindRealmViewHolder
メソッドで、NYTimesStory
はビューにバインドされます。
ストーリーの画像を表示するために、Glideを使用している点に注意してください。
部品の結合
ここまででほとんど完了しています。残っている作業は、RealmRecyclerView
とNYTimesStoryRecyclerViewAdapter
を接続することです。
これらを接続するには、Activityに次のコードを実装してください。
private RealmRecyclerView realmRecyclerView;
private NYTimesStoryRecyclerViewAdapter nyTimesStoryAdapter;
private Realm realm;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_grid_layout);
realmRecyclerView = (RealmRecyclerView) findViewById(R.id.realm_recycler_view);
setTitle(getResources().getString(
R.string.activity_layout_name,
getIntent().getStringExtra("Type")));
resetRealm();
Realm.setDefaultConfiguration(getRealmConfig());
realm = Realm.getDefaultInstance();
RealmResults<NYTimesStory> nyTimesStories =
realm.where(NYTimesStory.class).findAllSorted("sortTimeStamp", false);
nyTimesStoryAdapter = new NYTimesStoryRecyclerViewAdapter(this, nyTimesStories, true, true);
realmRecyclerView.setAdapter(nyTimesStoryAdapter);
final NYTimesDataLoader nyTimesDataLoader = new NYTimesDataLoader();
nyTimesDataLoader.loadAllData(realm, "YOUR_NY_TIMES_API_KEY");
}
@Override
protected void onDestroy() {
super.onDestroy();
realm.close();
realm = null;
}
private RealmConfiguration getRealmConfig() {
return new RealmConfiguration
.Builder(this)
.setModules(Realm.getDefaultModule(), new NYTimesModule())
.build();
}
private void resetRealm() {
Realm.deleteRealm(getRealmConfig());
}
ActivityのonCreate
メソッドで、Realmに対するクエリの結果としてRealmResults
を取得しNYTimesStoryRecyclerViewAdapter
へ渡します。NYTimesStoryRecyclerViewAdapter
のコンストラクタは、2つのboolean型のパラメータを持っていることに注意してください。これらは、元のクエリに対する新たな検索結果をアダプタが自動的に表示することと、グリッドアイテムがアニメーションされることを指定しています。
また、getRealmConfig()
メソッドが返すRealmのデフォルト設定としてセットしている点にも注意してください。これは、外部のライブラリであるcom.github.thorbenprimke:realm-nytimes-data
が提供するモデルクラスをスキーマに含める必要があるためです。
この時点でアプリケーションを実行することができますが、Realm
は空で、何も表示されません。
今、私たちは全ての繋ぎこみを完了させたので、データを準備する必要があります。ニューヨーク・タイムズはすばらしいAPIを提供してくれているので、“トップストーリー”APIを使用して最新のニュースを取得しグリッドに表示できます。
初期セットアップ時、Gradleの依存ライブラリにrealm-nytimes-data
を追加したことを思い出してください。このライブラリは、“トップストーリー”APIから送られてくるデータを表現するNYTimesStory
(ソース)とNYTimesMultimedium
(ソース)を含んでいます。
このチュートリアルを簡単にするために、APIからデータを取得する方法の詳細や、JSONデータをデシリアライズしてRealmオブジェクトを構築する方法の詳細については踏み込みません。代わりに、あなたがしなければならないことは、ニューヨーク・タイムズ開発者サイトで登録を行いAPIキーを取得することです。
そして、Activity中の以下のYOUR_NY_TIMES_API_KEY
の部分をあなたのAPIキーで置き換えてください。
nyTimesDataLoader.loadAllData(realm, "YOUR_NY_TIMES_API_KEY");
loadAllData
メソッドはAPIのレスポンスを取得し、Realmへの書き込みを行います。
データの読み込みが行われるようになったので、アプリケーションを実行してNYTimesのニュース記事の見出しがグリッドで表示されるはずです。
- もしあなたがデータの取得とJSONの解析の処理方法を知りたい場合は、サンプル・データ・プロジェクト内のメソッド
NYTimesDataLoader
(ソース)の実装を確認してください。このメソッドは、非同期API要求を実行し、JSONレスポンスを解析してRealmモデルに変換します。
About the content
This content has been published here with the express permission of the author.