私はここ数ヶ月間、IOS開発に取り組んでおり、Core DataとNSFetchedResultsControllerを広く使用してきました。Cursor、CursorAdapter、LoaderManager、Loaderの関係
コアデータ+ NSFetchedResultsController:データベースへの変更を自動的に検出し、それに応じてテーブル要素を更新します。
私はAndroid開発に切り替えました。私は上記と同等のものを探していました。私は利用可能なさまざまなクラスを見てきましたが、ちょっと混乱しています。クラスの
異なる種類:
- カーソル:データベースクエリの結果へのアクセスを提供します。
- CursorAdapter:(list、recycler)ビューをカーソルとリンクし、オブジェクトを表示します。
- ContentProvider:データベースオブジェクトへのアクセスを提供します。 LoaderManagerの使用に必要です。
- LoaderManager:UIをブロックせずにデータを読み込むためにアクティビティまたはフラグメントによって実装される
- ローダー:コンテンツが変更されたときにカーソルオブジェクトを生成するローダー。
私はgreendaoを使用していることに言及する価値があると思います。私は生成されたContentProviderを使用しています。私は少しあやふやだところ
これを更新する流れがある
。これは私の前提です。
- コンテンツプロバイダは、LoaderManagerおよび場合によってはCursorAdapterによって使用されるカーソルを保持します。
- データベースから変更が発生すると、LoaderにはForceLoadContentObserverがあり、その内容が変更されたときにカーソルを観察してonLoadFinishedを呼び出します。
- 通常、カーソルアダプタは
onLoadFinished()
内にswap()
を呼び出し、テーブルを更新します。心の中で上記を維持
、私はのContentProviderを作成し、LoaderManagerを実施したが、私は(greenDaoを使用して)新しいオブジェクトを永続化するとき機能onLoadFinished()
が呼び出されていない - 私は理解していますかどうかを問う開始するために私を導きましたプロセスは正しく行われます。これまでに私が一般的にコーディングしたことを示すためのコードスニペットがあります。
断片クラス
public class MissionPageFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
// Various initialization methods
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getLoaderManager().initLoader(0, savedInstanceState, this);
}
@Override
public Loader onCreateLoader(int id, Bundle args) {
ContentProvider.daoSession = Main.daoSession;
Uri uri = ContentProvider.CONTENT_URI;
// Other initializations
CursorLoader cursorLoader = new CursorLoader(getContext(), uri, projections, null, null, null);
return cursorLoader;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
System.out.println("Should be called when a new item is persisted... but not called =(");
}
// Other methods
}
誰かが私が正しくプロセスについて考えていますかどうかの確認および/または間違っているかもしれないものに光を当てることができれば、私はそれをたくさんいただければ幸いです。ここ
編集1
はgreenDaoによって生成のContentProviderサブクラスにおいてquery()
関数の抜粋です。
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
int uriType = sURIMatcher.match(uri);
switch (uriType) {
case MISSION_DIR:
queryBuilder.setTables(TABLENAME);
break;
case MISSION_ID:
queryBuilder.setTables(TABLENAME);
queryBuilder.appendWhere(PK + "="
+ uri.getLastPathSegment());
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
SQLiteDatabase db = getDatabase();
Cursor cursor = queryBuilder.query(db, projection, selection,
selectionArgs, null, null, sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
ソリューション
私はちょうど私がGreenDaoと、前述のすべてのクラスを実装する方法を共有したいと思いました。これを行うより良い方法があれば教えてください。しかし、これで十分です。
GreenDaoGeneratorクラスにContentProviderのサブクラスのメソッドが適切に呼び出された場合
Entity entity = new Entity(); entity.addContentProvider();
チェックを次のコードスニペットを追加することによって、ContentProviderのサブクラスを生成します。 AndroidManifest.xmlにjavadocの部分を追加します。私にとっては、生成されたContentProviderクラス
BASE_PATH
変数を次のような別の変数に変更する必要がありました。public static final String BASE_PATH = "MYTABLENAME";
LoaderManager、Loaderを上記のようなActivity/Fragmentクラスに追加します。また、ContentProviderが使用される前に
daoSession
オブジェクトを設定する必要があります。以下のスニペットを別のイニシャライザクラスに移動して、他のアクティビティ/フラグメントクラスでも使用できるようにしました。ContentProvider.daoSession = Main.daoSession;
私はので、私はここにhttps://gist.github.com/skyfishjy/443b7448f59be978bc59少しカスタマイズして提供CursorRecyclerViewAdapterクラスをサブクラス化RecyclerViewを使用しています。 ListViewを使用している場合は、単純なCursorAdapterを使用することができます。
Loader
は更新を待機しているので、Adapter
は更新を受信する必要はありません。今のContentProviderサブクラスはこれによりライン自動的GreenDaoによって生成さ
getContext().getContentResolver().notifyChange(uri, null);
にビューを更新することができます。これは、すべてのCRUD操作にContentProviderを使用でき、ビューが自動的に更新されることを意味します。これは、ORMを使用する目的を無効にしたようです。このように、私は現在通常のGreenDao操作を行い、挿入、削除、更新のたびに手作業で
notifyChange
を呼び出します。GreenDaoObj obj = new GreenDaoObj(); obj.insert(); getContext.getContentResolver().notifyChange(MyContentProvider.CONTENT_URI, null);
私は本当にGreenDaoがモデルとダオオブジェクトのためのコードを生成触れたくないとしてこれよりも良い方法があるとは思いません。私は、生成されたCRUDメソッドをネストするカスタムCRUD関数を追加することができますが、それは簡単ではないはずです。
私はこれまで見てきましたが、GreenDaoをLoader/LoaderManagerで使用する方法については十分に文書化されていませんでしたので、ここで整理すると思いました。うまくいけば、これはこれを実装しようとしている人に役立ちます。
LoaderおよびLoaderManagerは、コンテンツを読み込むためのクラスです。これはカーソルにすることもできますが、Jsonやその他のものにすることもできます。また、ローダなしでSQLiteからデータをロードすることもできます。しかし、あなたの例では、ContentProviderはSQLiteからデータをロードし、Cursorを返します。これを行うには、ContentProviderで 'query'をオーバーライドする必要があります(AndroidManifestに追加することを忘れないでください)。 –
私はgreendaoによって生成されたContentProviderサブクラスを使用しています。 (私はContentProviderクラスの専門家はいませんが) – jrhee17
あなたのAndroidManaifestにContentProviderを追加しましたか? - > http://developer.android.com/guide/topics/providers/content-provider -creating.html#ProviderElement –