3

実行からの同期後にViews更新Fragmentsするためのエレガントなソリューションはありますか?FragmentActivity's ViewPagerServiceSyncAdapter

ビュー ( )だけでなく、アダプタでもnotifyDataSetChanged()とを呼び出してみましたが、役に立ちませんでした。おそらく、私は間違った場所からそれらを呼び出していたのでしょう。フラグメントが表示されるたびにトリガーされることを期待して、where =true で実行しようとしましたが、機能しません。notifyDataSetInvalidated()refreshDrawableState()GridViewssetUserVisibleHintisVisible

また、データのニーズに合わせて、 ではなく SQLite データベースへの ASync 呼び出しを使用していますContent Provider。これにより、これが少し簡単になったと思います。なしでそれを行う方法はいくつか考えられますがContent Provider、どちらもあまり良くありません。

何か案は?必要に応じてコードを提供できます。ありがとう。

4

3 に答える 3

4

説明のために、カーソルをロードするために AsyncTask を使用していると仮定しますが、Loader や ThreadPool などを使用している場合でも同じように機能します。

サービスから、新しいデータが変更されるとすぐにLocalBroadcast. アクティビティがある場合とない場合があるため、ブロードキャストは、新しいデータがあることを知らせる良い方法です。したがって、あなたが行うサービスから:

    // that's an example, let's say your SyncAdapter updated the album with this ID
    // but you could create a simply "mybroadcast", up to you.
    Intent i = new Intent("albumId_" + albumId);
    LocalBroadcastManager.getInstance(this).sendBroadcast(i);

次に、カーソルを持つアクティビティ/フラグメントから、次のようにこのブロードキャストをリッスンします。

    public void onResume(){
        // the filter matches the broadcast
        IntentFilter filter = new IntentFilter("albumId_" + albumId); 
        LocalBroadcastManager.getInstance(this).registerReceiver(myReceiver, filter);
    }
    public void onPause(){
        LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceiver);
    }

    // and of course you have to create a BroadcastReceiver
    private BroadcastReceiver myReceiver = new BroadcastReceiver(){
       @Override
       public void onReceive(Context context, Intent intent){
           // here you know that your data have changed, so it's time to reload it
           reloadData = new ReloadData().execute(); // you should cancel this task onPause()
       }
    };

先ほど言ったように、この次の部分は、カーソルをロードするために使用しているスレッド化方法によって異なります。この例では、非常に人気があるため、AsyncTask で示します (しかし、あなたと世界中のすべての開発者が使用する必要があると本当に信じています)。ローダー パターン)。

private class ReloadData extends AsyncTask<Void, Void, Cursor> {
 protected Cursor doInBackground(Void... void) {
     // here you query your data base and return the new cursor
     ... query ...
     return cursor;
 }

 protected void onPostExecute(Cursor result) {
     // you said you're using a subclass of CursorAdater
     // so you have the method changeCursor, that changes the cursor and closes the old one
     myAdapter.changeCursor(result);
 }

}

上記のアプローチは、以前にテストして使用したものであり、機能することがわかっています。フラグFLAG_REGISTER_CONTENT_OBSERVERとオーバーライドonContentChanged()を使用してクエリを再実行し、カーソルを交換する方法がありますが、テストしたことはありません。それはそのようなものになります:

CursorAdapter(Context context, Cursor c, int flags)フラグFLAG_REGISTER_CONTENT_OBSERVERとオーバーライドを渡すコンストラクターでアダプターを初期化しますonContentChanged()。onContentChanged 内で、上記と同様に AsyncTask を実行します。LocalBroadcastManagerこの方法では、データベースが警告するので、を使用する必要はありません。その方法が私の主な答えではない理由は、それをテストしたことがないからです。

autoRequeryUI スレッドでデータの読み込みを実行するため、推奨されていないことに注意してください。

編集:

コンテンツ オブザーバーが API 11 のものであることに気付きました。2 つのオプションがあります。1 代わりにサポート ライブラリを使用します: https://developer.android.com/reference/android/support/v4/widget/CursorAdapter.htmlまたはブロードキャスト オプション

于 2013-12-05T09:56:08.133 に答える
0

新しいデータを使用してアダプターを最初から再作成し、それを ListView (または任意のビュー) に再割り当てします。

于 2013-12-11T08:59:59.007 に答える