2017-01-26 9 views
1

Firebaseはすばらしいリアルタイムデータベースサービスを提供しますが、これは私の傑出したものであり、このエンジンがメインのローカルストレージ(オフラインモード)として使用されたときの私の経験を示唆しています。AndroidベースのFirebaseリアルタイムデータベース読み込み指示

アプリが一部のデータを要求しているときに、プロセスの何らかの兆候が見られるとはどういうことが予想されますか?しかし、私はそれを働かせるための直接的な機能性は見つけていません。

私はカスタムソリューションを作成し、コミュニティからのレビューを取得したいと考えています。

答えて

0

アイデアは単純です:ValueEventListenerを、いくつかのversionタグにバインドします。このタグは、データを更新してその状態を変更するSingleValueEventコールバックでリクエストを作成します。

と仮定、私はUserオブジェクトを持っていると私は、タイムスタンプの内容とverプロパティを追加するバージョン管理のために:

users : { 
    id : { 
     name : 'Mr. Anderson', 
     ver : '<timestamp>' 
    } 
} 

データ状態を確認するために私がenum Stateinterface StateIndicatableinterface OnStateChangeListenerを紹介:

enum State{ INIT, LOADING, LOADED, FAILED } 

interface OnStateChangeListener{ 
    void stateChanged(State newState); 
} 

interface StateIndicatable{ 
    State getState(); 
    void setOnStateChangeListener(OnStateChangeListener listener); 
    void clearOnStateChangeListener(); 
} 

私はwouldn Userモデルを変更したいと思います。ビュー/プレゼンテーション/ビューモデルのレベルに存在するラッパーを使用します:

私は、任意のバージョン管理モデルを中心に抽象ラッパーを作成したいと思います。ここでは

abstract class FirebaseVersionedModelWrapper<M> implements StateIndicatable{ 

    int version; 
    protected WeakReference<M> modelRef; 
    State state; 
    OnStateChangeListener onStateChangeListener; 
    DatabaseReference verRef; 

    FirebaseVersionedModelWrapper(M model, String firebasePath, OnStateChangeListener onStateChangeListener){ 
     this.modelRef = new WeakReference(model); 
     this.state = State.INIT; 
     this.onStateChangeListener = onStateChangeListener; 
     verRef = FirebaseDatabase.getInstance().getReference(firebasePath + "/ver"); 
     verRef.keepSynced(true); 


     verRef.addValueEventListener(
       new OnValueEventListener(){ 

        @Override 
        public void onDataChange(DataSnapshot dataSnapshot) { 
         if(modelRef.get()==null){ 
          verRef.removeEventListener(this); 
          return; 
         } 

         if(dataSnapshot.hasChild("ver"){ 
          if(dataSnapshot.child("ver").getValue(Integer.class) != version){ 
           requestUpdate(); 
          } 
         } 
         else 
          setState(State.FAILED); 
        } 

        @Override 
        public void onCancelled(DatabaseError databaseError) { 
         if(modelRef.get()==null){ 
          verRef.removeEventListener(this); 
          return; 
         } 

         setState(State.FAILED); 
        } 
       } 
      ); 

    } 

    private void requestUpdate(){ 
     setState(State.LOADING); 

     DatabaseReference ref = FirebaseDatabase 
      .getInstance 
      .getReference(firebasePath); 
     ref.keepSynced(true); 

     ref.addListenerForSingleValueEvent(
       new OnValueEventListener(){ 

        @Override 
        public void onDataChange(DataSnapshot dataSnapshot) { 
         M model = modelRef.get(); 
         if (model==null) return; 
         if(dataSnapshot.hasChild("ver")){ 
          version = dataSnapshot.child("ver").getValue(Integer.class); 
          setFields(model, dataSnapshot); 
          setState(State.LOADED); 
         } 
         else{ 
          setState(State.FAILED); 
         } 
        } 

        @Override 
        public void onCancelled(DatabaseError databaseError) { 
         setState(State.FAILED); 
        } 
       } 
      ); 
    } 

    private void setState(State newState){ 
     if (this.state == newState) return; 

     this.state = newState; 

     if (onStateChangeListener != null) 
      onStateChangeListener.stateChanged(newState); 
    } 

    @Override 
    public State getState(){ 
     return this.state; 
    } 

    @Override 
    public void setOnStateChangeListener(OnStateChangeListener listener){ 
     this.onStateChangeListener = listener; 
    } 

    @Override 
    public void clearOnStateChangeListener(){ 
     this.onStateChangeListener = null; 
    } 

    protected abstract void setFields(M model, DataSnapshot dataSnapshot); 

} 

DatabaseReference#keepSynced(true)は、データパス上の要求が新鮮なデータを返すことを確認するために呼ばれています。これは論議的なアプローチであり、今私の練習では完全には確認されていません。

その後、私はUserWrapperUserをラップ:

class UserWrapper extends FirebaseVersionedModelWrapper<User>{ 

    FirebasedUser(User userModel, String userPath, OnStateChangeListener listener){ 
     super(userModel, userPath, listener); 
    } 

    @Override 
    void setFields(User model, DataSnapshot dataSnapshot){ 
     // setting values for model 
    } 
} 

、最終的に私がOnStateChangeListenerコールバックにラッパーとバインド表示ルーチンをインスタンス化することができます

まあ
User user = new User(); 

UserWrapper wrapper = new UserWrapper(
    user, 
    new OnStateChangeListener(){ 

     @Override 
     void stateChanged(State newState){ 
      if(newState == State.LOADED){ 
       showUserDetails(); 
      } 
      else if(newState == State.FAILD){ 
       showErrorState(); 
      } 
      else{ 
       showLoadingIndicator(); 
      } 
     } 

    } 
); 

、私が言ったように、任意の意見やここに掲載されている代替ソリューションは大変ありがとう!

コードはメモリからタイプされており、間違いの可能性があります。

関連する問題