2017-12-09 14 views
0

私はFirebaseを使用してデータを保存しています。 Firebaseのメソッドとメソッドをアクティビティで分離しようとしています。例えば、私は "FirebaseMethodsHelper"と呼ばれるクラスを作成しました。そこには、すべてのFirebaseメソッドを記述したいと思います。 たとえば、すべてのユーザーをリストに戻す「getAllUsers」メソッド。 唯一の問題は私はそれが動作していないことがあります。Androidのfirebaseがnullになる

私は間違って何をしているのかわかりません。だから皆さん、私を助けてください。

断片

public class MyPlayListFragment extends Fragment { 
    private FirebaseDatabase refToVideos; 
    private FirebaseUser currentUser; 
    private ArrayList<Video> videosList; 
    private VideoViewAdapter adapter; 
    private RecyclerView rvVideos; 
    private List<Video> checkList; 


public MyPlayListFragment() { 
    // Required empty public constructor 
} 


@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 
    // Inflate the layout for this fragment 
    View v = inflater.inflate(R.layout.fragment_my_play_list, container, false); 
    rvVideos = (RecyclerView)v.findViewById(R.id.rvVideos); 

    return v; 
} 

@Override 
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 
    super.onViewCreated(view, savedInstanceState); 
    videosList = new ArrayList<>(); 
    refToVideos = FirebaseDatabase.getInstance(); 
    currentUser = FirebaseAuth.getInstance().getCurrentUser(); 

    FirebaseMethodsHelper fmh = new FirebaseMethodsHelper(); 


    checkList = fmh.getAllVideosFromDB(currentUser); 
    if(checkList != null) 
    Log.d("checkList",checkList.toString()); 

FirebaseMethodHelperクラス

public class FirebaseMethodsHelper { 
private FirebaseDatabase databaseRef; 
private ArrayList<User> usersList; 
private ArrayList<Video> videosList; 



    public List<Video> getAllVideosFromDB(FirebaseUser currentUser){ 
     databaseRef = FirebaseDatabase.getInstance(); 
     databaseRef.getReference(Params.VIDEOS).child(currentUser.getUid()).addListenerForSingleValueEvent(new ValueEventListener() { 
      @Override 
      public void onDataChange(DataSnapshot dataSnapshot) { 
       for (DataSnapshot snapshot : dataSnapshot.getChildren()){ 
        videosList.add(snapshot.getValue(Video.class)); 
       } 
      } 

      @Override 
      public void onCancelled(DatabaseError databaseError) { 

      } 
     }); 


    return videosList; 
    } 
} 

は、私はなぜ知らないが、それは常にnullを返します。

答えて

2

これは非同期Web APIの古典的な問題です。まだをロードできません。まだロードされていません。

Firebaseデータベース(および最新のWeb API)のデータは、時間がかかる可能性があるため、非同期に読み込まれます。データを待たずに(ユーザーのアプリケーションレスポンスダイアログにつながる)、データがセカンダリスレッドにロードされている間は、メインアプリケーションコードが続行されます。データが利用可能になると、onDataChange()メソッドが呼び出され、データを使用できます。

これにより、アプリのフローが変更されます。リスナー

を取り付けた後、リスナー

を取り付ける前

:次のシーケンスを出力します。このコードを実行する

public List<Video> getAllVideosFromDB(FirebaseUser currentUser){ 
    databaseRef = FirebaseDatabase.getInstance(); 
    System.out.println("Before attaching listener"); 
    databaseRef.getReference(Params.VIDEOS).child(currentUser.getUid()).addListenerForSingleValueEvent(new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot dataSnapshot) { 
      System.out.println("Got data"); 
     } 

     @Override 
     public void onCancelled(DatabaseError databaseError) { 
      throw databaseError.toException(); // don't ignore errors 
     } 
    }); 
    System.out.println("After attaching listener"); 
} 

:これを見るための最も簡単な方法は、いくつかのログステートメントを配置することによって、ありますデータを入手

Thおそらくあなたが期待したものではありませんが、あなたがそれを返すときに配列が空である理由を正確に説明します。

ほとんどの開発者にとっての初期の対応は、この非同期動作を「修正」することです。 Webは非同期であり、早ければ早ければ早く、現代のWeb APIで生産性を上げる方法を学ぶことができます。

この非同期パラダイムの問題を再構築するのが最も簡単だとわかりました。 「最初にすべてのビデオを取得してからログを取る」と言うのではなく、「すべてのビデオの取得を開始します。

これは、ビデオを必要とするコードはonDataChange()(または内部から呼び出される)である必要があることを意味します。例:前に非同期APIを扱っていない開発者にとっては、これは一般的な問題です。そのように、そこにすでに話題にかなりいくつかの質問されて、そして私はあなたがあまりにもそれらをチェックアウトをお勧めしています

+0

お返事ありがとうございます。私はそれらのリンクをチェックします! –

1

リストvideosListはまだ初期化されていません。また、あなたのメソッドでリストを返すあなたのアプローチは間違っています。 firebase呼び出しは非同期で、データがいつ利用可能になるかを制御することはできません。ほとんどの場合、メソッドはnull(リストが初期化されていない場合)または空のリスト(初期化された場合)を返します。

ソリューションは、必要に応じて、これはあなたのフラグメントに動画のリストを返します、インターフェイスのコールバックを使用することです:

public interface FirebaseCallback { 
    void listVideos(ArrayList<Video> videos); 
} 

この方法は、あなたのFirebaseMethodHelperクラスから呼び出されます。

public void getAllVideosFromDB(FirebaseUser currentUser, FirebaseCallback callback){ 
    databaseRef = FirebaseDatabase.getInstance(); 
    databaseRef.getReference(Params.VIDEOS).child(currentUser.getUid()).addListenerForSingleValueEvent(new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot dataSnapshot) { 
      ArrayList<Video> videosList = new ArrayList<>(); 

      for (DataSnapshot snapshot : dataSnapshot.getChildren()){ 
       videosList.add(snapshot.getValue(Video.class)); 
      } 

      callback.listVideos(videosList); 
     } 

     @Override 
     public void onCancelled(DatabaseError databaseError) { 

     } 
    }); 
} 

あなたの断片から、インターフェイスを実装し、を次のようにメソッドに渡します。

+0

うわー答えをつかんで、ありがとう! –

関連する問題