2016-11-15 11 views
1

Firebaseデータベースから取得した値をArraylistに追加し、そこからString配列に追加しようとしています。私の検索方法はうまくいきます。私はトーストですべての値をプリントアウトすることができます。しかし、明らかにそれはarraylistに追加されません。Firebase/Android:Firebaseから取得した値をarraylistに追加するとnullポインタ例外が返される

フラグメントクラスのonActivityCreated()で取得するコードは次のとおりです。

ArrayList<String> allBrands = new ArrayList<>(); 
brandRef=FirebaseDatabase.getInstance().getReferenceFromUrl("https://stockmanager-142503.firebaseio.com/Brands"); 
     q=brandRef.orderByChild("brandName"); 
     q.addChildEventListener(new ChildEventListener() { 
      @Override 
      public void onChildAdded(DataSnapshot dataSnapshot, String s) { 
       allBrands.add((dataSnapshot.getValue(Brand.class)).getBrandName()); 
       Toast.makeText(getActivity(),(dataSnapshot.getValue(Brand.class)).getBrandName(), Toast.LENGTH_SHORT).show(); 

      } 

      @Override 
      public void onChildChanged(DataSnapshot dataSnapshot, String s) { 

      } 

      @Override 
      public void onChildRemoved(DataSnapshot dataSnapshot) { 

      } 

      @Override 
      public void onChildMoved(DataSnapshot dataSnapshot, String s) { 

      } 

      @Override 
      public void onCancelled(DatabaseError databaseError) { 

      } 
     }); 

は、そして、これは私がOnActivityResultでのArrayList(フラグメントクラスの)メソッドを使用しようとしているが、イテレータのループは、私は信じて実行されていないところです。トーストは見られません。配列を操作しようとするとnullポインタ例外が発生します。値がブランド配列にコピーされないと仮定します。

count=allBrands.size(); 
           String[] brands=new String[count]; 
           Iterator<String> itemIterator = allBrands.iterator(); 
           if(itemIterator.hasNext()){ 
            //brands[i] = itemIterator.next(); 
            Toast.makeText(getActivity(), itemIterator.next(), Toast.LENGTH_SHORT).show(); 
            // i++; 

           } 
           for(i=0;i<count;i++){ 
            if(brands[i].compareTo(Brand)==0){ 
             f=1;break; 
            } 
           } 

ここに私のデータベースが役立ちます。しかし、私は問題のないトーストですべての検索値を印刷することができます。私はあなたがすべてのデータを非同期Firebaseからロードされているという事実に刺される疑いで

Database

答えて

2

それは、あなたが共有コードから特定することは難しいです。あるいは、単にデータを読み取る権限がない場合もあります。私は両方の答えを与えます。データが非同期

ロードされ

それはあなたのコードの最低限のスニペットに、いくつかのログステートメントを追加するとき、この動作を理解することが最も簡単です:

System.out.println("Before attaching listener"); 
q.addChildEventListener(new ChildEventListener() { 
    public void onChildAdded(DataSnapshot dataSnapshot, String s) { 
     System.out.println("In onChildAdded");  
    } 
    public void onChildChanged(DataSnapshot dataSnapshot, String s) { } 
    public void onChildRemoved(DataSnapshot dataSnapshot) { } 
    public void onChildMoved(DataSnapshot dataSnapshot, String s) { } 
    public void onCancelled(DatabaseError databaseError) { } 
}); 
System.out.println("After attaching listener"); 

このスニペットの出力は次のようになります。

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

を取り付ける前に

onChildAddedで

(おそらく複数回)

これはあなたが出力を期待できないため、おそらくですFirebaseは(ほとんどのクラウドのAPIのような)非同期データベースからデータをロードするためです:。代わりに待っていますデータを返すために、メインスレッドでコードを実行し続け、データが利用可能なときにChildEventListener.onChildAddedにコールバックします。

Androidでデータを待つ方法はありません。もしあなたがそうするなら、あなたのユーザーは、恐ろしい "Application Not Responding"ダイアログを得て、あなたのアプリは殺されるだろう。

だから、このAPIの非同期性に対処するための唯一の方法は、(いくつかの点で、あまりにも他のコールバックに、おそらく)onChildAdded()コールバックに新しいデータを持っている必要があり、コードを置くことです:

q.addChildEventListener(new ChildEventListener() { 
    public void onChildAdded(DataSnapshot dataSnapshot, String s) { 
     allBrands.add((dataSnapshot.getValue(Brand.class)).getBrandName()); 
     System.out.println(allBrands.length); 
    } 

データを読み取る権限が必要です

ロケーションからデータを読み取る権限が必要です。パーミッションがない場合、Firebaseはただちにリスナをキャンセルします。コード内でこの条件を処理する必要があります。そうでないと、決して知らないでしょう。

public void onCancelled(DatabaseError databaseError) { 
    throw databaseError.toException(); 
} 
+0

ありがとうございます。取得したデータをonActivityResultメソッドに渡すことは可能でしょうか?そうすれば、アプリは検索が完了するまで待つでしょうか? –

+0

'OnActivityResult()'は 'ChildEventListener'のメソッドの中から呼び出すことができます。これらのメソッドはメインスレッドで呼び出されます。 –

0

あなたはそれが最後になる前に、我々はrereshを実装見ることができるように(あまりにも..私は自分の将来の参照にこれを書いている)

これを試してみてください。おそらくそれを行うより良い方法があります。ただし、これは文書化されていません。また、このイベントのすべてのListnersは自発的に追加し、firebaseによって自動的にリリースする必要がありますが、何らかの理由でそれをしません。

/** 
    * @param uid User's ID 
    * @param Callable send as null just to implement a call to assure the callback is updapted before it's finished 
    * @return returns ArrayList of all Games unique identification key enlisted in a User 
    */ 
    private final ArrayList<String> mGamesPlaying = new ArrayList<>(); 
    public ArrayList<String> mGamesPlaying(final String uid, final Callable refresh) { 


    final Firebase ref = FirebaseRef; 
    Firebase usersRef = ref.child("users").child(uid).child("playing_games"); 

    usersRef.addValueEventListener(new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot snapshot) { 

     mGamesPlaying.clear(); 
     for (DataSnapshot child : snapshot.getChildren()) { 
      Log.d(TAG, "Test Game" + child.getKey()); 
      mGamesPlaying.add(child.getKey()); 
     } 

      try { 

      refresh.call(); 
      } catch (Exception e) { 
      e.printStackTrace(); 
      } 

     } 

     @Override 
     public void onCancelled(FirebaseError firebaseError) { 
     } 
    }); 

    return mGamesPlaying; 
    } 
関連する問題