20

このような多くの質問を検索しましたが、どれにも答えが見つかりませんでした。

アクション バーからアクセスできる 3 つのタブがあるアクティビティがあります。これは、ビュー クラスを拡張して作成したカスタム ビューを拡張する 3 つのフラグメントを追加することで実現しました。

データベースが変更された時点で、invalidate()/postinvalidate() を呼び出してタブのビューを更新しようとしましたが、うまくいきません。私が検討した他の多くのオプションと同じように、フラグメントの onCreateView を呼び出す場合も同じことが言えます。

ただし、別のタブに移動して戻ると、変更が行われており、ビューが更新されているはずです。

別のタブに変更したときに発生するのと同じことをシミュレートするにはどうすればよいですか? 何が起こるか。Fragment のライフサイクルを調べてみました (onCreateView() を呼び出そうとしました)。

別のタブに切り替えるとデータが変更されるため、データは適切に読み込まれます。

関係がなくなったので、コードの一部を削除しました。変更を通知するために、独自の Observer パターンの代わりに Cursorloaders を実装しました。これが今の私の主な活動です。

問題は、これらのフラグメント内のビューを再描画したい場合、今何をすべきかです。fragmentObject.getView().invalidate() を適用すると機能しません。以前と同じ問題を抱えていますが、データベースの変更を通知するオブザーバーがローダーで適切に実装されました。

public class ArchitectureActivity extends Activity implements LoaderManager.LoaderCallbacks<Cursor> {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);     
    setContentView(R.layout.main);

    ActionBar actionbar = getActionBar();
    actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    ActionBar.Tab EditTab = actionbar.newTab().setText("Edit");
    ActionBar.Tab VisualizeTab = actionbar.newTab().setText("Visualize");
    ActionBar.Tab AnalyseTab = actionbar.newTab().setText("Analyse");

    Fragment editFragment = new EditFragment();
    Fragment visualizeFragment = new VisualizeFragment();
    Fragment analyseFragment = new AnalyseFragment();

    EditTab.setTabListener(new MyTabsListener(editFragment));
    VisualizeTab.setTabListener(new MyTabsListener(visualizeFragment));
    AnalyseTab.setTabListener(new MyTabsListener(analyseFragment));

    actionbar.addTab(EditTab);
    actionbar.addTab(VisualizeTab);
    actionbar.addTab(AnalyseTab);

    ArchitectureApplication architectureApplication = (ArchitectureApplication)getApplicationContext();
    architectureApplication.initialize();

    getLoaderManager().initLoader(0, null, this);
    getLoaderManager().initLoader(1, null, this);
}

public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    if (id == 0){
        return new CursorLoader(this, GraphProvider.NODE_URI , null, null, null, null);
    } else if (id == 1){
        return new CursorLoader(this, GraphProvider.ARC_URI , null, null, null, null);
    }
    return null;
}

public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    // Reloading of data, actually happens because when switching to another tab the new data shows up fine
    Log.e("Data", "loaded");
}

public void onLoaderReset(Loader<Cursor> loader) {
}
}
4

5 に答える 5

23
  1. 自分自身を呼び出そうとしないでくださいonCreateView()...これはライフサイクル メソッドであり、フレームワークによってのみ呼び出される必要があります。

  2. Fragmentは再利用可能な UI コンポーネントです。独自のライフサイクルがあり、独自のビューを表示し、独自の動作を定義します。通常、の動作は自己完結型であり、特定の から独立していなければならないためActivity、 の内部動作をいじる必要はありません。FragmentFragmentActivity

    Fragmentとはいえ、最善の解決策は、それぞれにインターフェースを実装させることだと思いLoaderManager.LoaderCallbacks<D>ます。それぞれFragmentが を初期化しLoader(つまり、SQLite データベースに裏打ちされたCursorLoaderを使用している場合)、 (1) バックグラウンド スレッドにデータをロードし、(2) に対して行われたコンテンツの変更をリッスンします。コンテンツの変更が発生するたびに新しいデータを配信します。ContentProviderLoaderonLoadFinished()

    このソリューションは、完全にイベント ドリブンであるため、現在のソリューションよりも優れています。データが配信されたときにビューを更新するだけで済みますonLoadFinished()(新しいタブをクリックするたびにデータ ソースが変更されたかどうかを手動で確認する必要はありません)。

  3. あなたが怠惰で手っ取り早い解決策が必要な場合は、FragmentonResume()メソッドでもビューを更新することで解決できる場合があります。

于 2012-10-07T17:21:44.603 に答える
4

次の方法で解決できる同様の(同一ではありませんが)問題がありました。

追加したフラグメントで

public void invalidate() {
    myView.post(new Runnable() {
        @Override
        public void run() {
            myView.invalidate();
        }
    });
}

フラグメントのビュー myView を更新したいときに、アクティビティからこのメソッドを呼び出しました。post() を使用すると、描画の準備が整ったときにのみビューが無効になります。

于 2014-05-21T22:36:42.617 に答える
3

フラグメント内のビューを更新するための回避策を見つけました。データベースが更新されるたびにビューを再作成しました(新しいCustomView)。その後、setContentView(CustomView view)を呼び出します。それはハックのように見えますが、それは機能し、私が試した他の何もしません。

私の問題は実際には解決されませんでしたが、私はAlexLockwoodに報酬を与えました。ローダーに関する彼のアドバイスは私のアプリケーションをより良くし、それは私が最終的に見つけた解決策を探し続ける原因となりました。

于 2012-10-12T19:15:35.693 に答える
2

同じ問題がありました。私の解決策は、フラグメントをデタッチして再度アタッチすることでした。

        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        Fragment f = getFragment(action);
        if(forceUpdate)
        {
            fragmentTransaction.detach(f);
            fragmentTransaction.attach(f);
        }
        fragmentTransaction.replace(R.id.mainFragment, f);
        fragmentTransaction.commit();
        currentAction = action;
于 2013-04-30T15:07:13.863 に答える