2017-09-18 5 views
1

私はアイテムのリストを表示するアプリケーションを開発しており、ユーザーはアイテムを追加してアイテムの詳細を確認することができます。Firebaseデータベースを使用してアクティビティを再開するときにデータを適切に復元する方法は?

ChildEventListenerリスナーonResume()を追加し、onPause()にそれらを取り除く、のは、私が活動中で、私のデータベース参照を保持するとしましょう:これらChildEventListener

public void onResume() { 
    super.onResume(); 
    mItemChildEventListener = mDatabaseReference.child('items').addChildEventListener(new ChildEventListener() { 
     public void onChildAdded(DataSnapshot dataSnapshot, String s) { 
      mAdapter.addItem(dataSnapshot.getValue(Item.class)); 
     } 
     ... 
    }; 
} 

public void onPause() { 
    super.onPause(); 
    if (mItemChildEventListener != null) { 
     mDatabaseReference.removeEventListener(mItemChildEventListener); 
    } 
} 

、私はアイテムのリストに項目によってアイテムを追加していると、アダプタにnotifyItemInserted(itemArray.size() - 1)を呼び出します。

public void addItem(Item item) { 
    if (mItems == null) { 
     mItems = new ArrayList<>(); 
    } 
    mItems.add(item); 
    notifyItemInserted(mItems.size() - 1); 
} 

はまた、スムーズに実行中のアプリケーションを維持するために、私はこれはonSaveInstanceState()値の保存とonCreate()にそれらを復元し、Reteiner Fragmentに項目のリストを保持しています。

しかし、私は登録解除し、再びリスナーを登録した場合、例えば、任意の方向の変化によって、または活性を残してreturtingは、予想通り、 onResume()が呼び出される
protected void onCreate(@Nullable Bundle savedInstanceState) { 
    if (savedInstanceState != null) { 
     mItems = getState(STATE_ITEMS); 
    } else { 
     mItems = new ArrayList<>(); 
    } 

    mAdapter = new ItemAdapter(mItems); 
} 

public void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 
    saveState(STATE_ITEMS, mItems); 
} 

public <T> T getState(String key) { 
    //noinspection unchecked 
    return (T) mRetainedFragment.map.get(key); 
} 

public void saveState(String key, Object value) { 
    mRetainedFragment.map.put(key, value); 
} 

public static class RetainedFragment extends Fragment { 
    HashMap<String, Object> map = new HashMap<>(); 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     // retain this fragment 
     setRetainInstance(true); 
    } 
} 

、再度ChildEventListenerを添加することにより、同じデータが検索されます。これは、項目リストに既に含まれているデータと比較されない場合は、mItemsと重複します。

また、mItemsの項目のリストを保持せずに、onResume()が呼び出されるたびにデータを取得すると、リストのスクロール位置が失われ、データの取得に時間がかかるため点滅します。

質問

は、どのように私は再びそれらを再度取得せずに検索された項目のリストを保持しますが、既に取得したアイテムの変更をして、コメントを追加新しいアイテムのために聞いておくことができますか?すでに検索されたアイテムを新しいアイテムと比較するよりも、たとえばそのキーによって解決する方が良いでしょうか?

私はドキュメントやその他の質問を調べてみましたが、この状況に関連する情報は見つかりませんでした。また、項目mItemsのリストで行ったように、mDatabaseReferenceの参照をonSaveInstanceState()に保存しようとしましたが、どちらも機能しませんでした。

+0

@rewgoes DatabaseHelperクラスがあり、データをArrayListにロードすることができる場合は、View HolderとしてRecyclerAdapterを使用していますか?それで、UpdateまたはDeleteを追加するときにDBを移動する必要があるだけです。私はSqliteで使用するMVP設計です – Grendel

+0

@grendel、私はDatabaseHelperを使用していません。私のデータベースは完全にfirebaseリアルタイムデータベースに基づいています。 – rewgoes

+0

@MarianoCórdobaこれらのパターンだけでは、OPが経験している問題を必ずしも助けるわけではありません。このように構築したインフラストラクチャは、データモデルレイヤーを保持するために何か特別なことをしない限り、構成の変更ごとに引き裂かれて再作成される可能性があります。 –

答えて

2
  1. Loader内でFirebaseを呼び出し、静的な変数やリストなどのデータ構造に保存するだけです。
  2. onCreateでローダーを初期化します。
  3. LoaderでonStartLoading()メソッドをオーバーライドし、onStart()でこのメソッドを呼び出します。
  4. onStartLoading()の内部では、静的変数がnullかどうかを単純にチェックします。 nullの場合は、startLoading。それ以外の場合はロードせず、以前のデータをデータソースとして設定します。
  5. ローダーを使用する利点は、向きが変更された場合、AsyncTaskのようにネットワーク呼び出しを行わないことです。
+1

OPは子リスナーを使用して、データベース内の特定の場所の変更を継続的に聴いています。ローダーは、データのペイロード全体が1回だけロードされると想定する傾向があるため、この戦略はあまりうまく機能しません。 –

+0

あなたの言っていることに私は同意しますが、私が言っているのは方向変更の問題です。子リスナーを登録したままにして、通常通り使用してください。しかし、ローダーを使用して最初に一度読む。そして、あなたはアプリケーションonStart()に戻るときにそれらを使用します。 – Aman

+0

また、回答に書いたとおりに、ローダーを使用して一度読んでデータをキャッシュし、オフラインで使用することができます。しかし、たとえキャッシュしても、初めて(onStart()のケースを使用せずにオフラインデータを照会しても)読むことができます – Aman

2

Firebase Realtime Database SDKのenable persistenceを使用すると、すでに受信している不要なデータの取得を防ぐことができます。SDKは、ローカルにデータをフェッチし、それが利用可能なとき最初にそのデータを使用することを好むキャッシュします:

FirebaseDatabase.getInstance().setPersistenceEnabled(true); 

が、これがどのように動作するかを理解するためにread the documentationにしてください。

また、onStartとonStopの間にリスナーを開始および停止するのは、従来のことです。これにより、アプリが一瞬フォーカスを失った場合(たとえば、ダイアログがポップアップする、または他の透明なアクティビティが上に表示された場合など)、さらに多くの再読み込みを避けることができます。

関連する問題