65

Android コンテンツ プロバイダのドキュメントではContentResolver、 から取得したgetContentResolver()を使用してコンテンツにアクセスする方法について説明しています。

ただしContentProviderClient、 から入手できる もありますgetContentResolver().acquireContentProviderClient(authority)ContentResolverプロバイダーからコンテンツにアクセスするために使用できるメソッドとほぼ同じメソッドを提供しているようです。

を直接使用するContentProviderClient代わりに、いつ使用する必要がありContentResolverますか? 利点は何ですか?

4

5 に答える 5

96

Androidデバイスには多くのデータベースがあり、それぞれが一意のコンテンツ機関によって識別されます。これは、content://uriの「ドメイン名」に相当する部分です。最初のスラッシュの前のすべてです。

ContentResolverString contentAuthorityからへのマッピングを提供するデータを格納しますContentProviderContentResolver.query()orまたはwhatを呼び出すとupdate()、URIがそのコンポーネントに解析され、contentAuthority文字列が識別され、contentResolverはそのマップで一致する文字列を検索し、クエリを適切なプロバイダーに送信する必要があります。URIは呼び出しごとに異なり、contentAuthorityも異なる可能性があるため、このコストのかかる検索はすべての呼び出し中に発生します。さらに、その特定のプロバイダーへの接続のセットアップと切断に関連するコストが発生する可能性があります。これは、呼び出し間で再利用することはできません。そこに含まれるオーバーヘッドについてはよくわかりません。これはかなり深いOSレベルのコードです。

対照的に、あなたが電話するときacquireContentProviderClient(authority)、それは「私は何を提供する必要がありますか?」ルックアップは1回実行され、ContentProviderClient基本的にへの直接リンクであるが与えられますContentProvider。(クロススレッド通信と同時実行ロックを含む、あなたとプロバイダーの間には少し接着剤があります)。ただし、を使用する場合はContentProviderClient、要求した権限についてプロバイダーに直接問い合わせます。これにより、「どのプロバイダーが必要ですか?」を絶えず再計算する無駄がなくなります。

注:acquireContentProviderClient()ドキュメントごと:ContentProviderClientを取得する場合、「呼び出し元は、ContentProviderClient.release()を呼び出して、プロバイダーで完了したことを示す必要があります。これにより、システムはプロバイダーを解放できるようになり、他にプロバイダーがないと判断されます。それをアクティブに保つ理由。」 したがって、基本的に、古いクライアントを開いたままにすると、プロバイダーはバックグラウンドでサービスとして実行され続けるようになります。だから、クリーンアップすることを忘れないでください!

概要:

さまざまなcontentAuthoritiesへの多くの呼び出し: を使用しContentResolverます。

同じ機関への繰り返しの呼び出し: を取得して使用しますContentProviderClient。完了したら、必ずrelease()してください。

于 2011-03-08T14:14:07.810 に答える
8

わかりましたが、 ContentProviderがアクティビティと同じプロセスで実行されている場合にのみ機能することに注意してください。

メソッドのドキュメントからのメモgetLocalContentProvider():

ContentProvider が別のプロセスで実行されている場合は、null が返されます。これは、プロバイダーと同じプロセスで実行していることがわかっていて、その実装の詳細に直接アクセスしたい場合に使用できます。

于 2012-10-29T07:54:24.210 に答える
5

別のインポートの違いは、ContentProviderClient をカスタム プロバイダー オブジェクトにキャストして、CRUD 以外の他のメソッドにアクセスできることだと思います。

ContentProvider cp = getContentResolver().acquireContentProviderClient(mCurUri).getLocalContentProvider();
yourProvider fld = (yourProvider)cp;
fld.query(...);           // you can query as ContentResolver
fld.addFolder(newFolder); // also can invoke the extend method of your custom ContentProvider
于 2012-07-23T12:11:33.760 に答える
2

次の違いが見つかりました。アプリ A に独自のカスタム contentprovider を作成しました。アプリ B にホームスクリーン ウィジェットを作成しました。ウィジェットから ContentResolver を介してアプリ A の ContentProvider にアクセスしようとすると、「プロバイダーが見つかりませんでした」というメッセージが表示されました。情報」エラー。代わりに、ContentResolver を介して ContentProviderClient を取得し、ContentProviderClient を介してクエリを実行すると、機能します。ContentResolver の代わりに ContentProviderClient のみを使用して、他に何も変更する必要はありませんでした。その振る舞いについての本当の説明はなく、インターネット上でなぜそうなのかについての情報も見つかりませんでした. これがウィジェットの特別な癖であるかどうかはわかりません。アプリ B のアクティビティから試していないためです (アプリ B は単なるウィジェットであり、アクティビティはありません)。

于 2012-03-09T21:17:29.633 に答える
0

ContentProviderClient の使用法の 1 つは、テストで ContentProvider のいくつかのメソッドにアクセスするのに役立ちます。たとえば、単体テストでshutdown()メソッドを使用して、複数のコンテンツ プロバイダーをインスタンス化する複数のテストを回避しています。

次のように実装ContentProvider#shutdown()します。

@Override
public void shutdown() {
    openHelper.close();
    super.shutdown();
}

そして、テスト メソッドの最後で、shutdown()を使用して呼び出してContentProviderClientテストをクリーンアップし、他のテストがコンテンツ プロバイダーを使用できるようにします。

getContext()
       .getContentResolver()
       .acquireContentProviderClient(URI)
       .getLocalContentProvider()
       .shutdown();
于 2016-04-08T13:32:03.537 に答える