2017-01-03 7 views
0

私が苦労しているのは、Firebaseへの非同期呼び出しを使って見栄えの良いコードを書く方法です。以下は、Firebaseからすべてのユーザと現在のユーザを取得し、選択した場所の間の距離をチェックする私の関数のコードです。これらのFirebase ValueEventListenersを読み取り可能にするにはどうすればよいですか?

実際にValueEventListenersをそれぞれ別々の機能に移動することはできません。それらはすべて連続して起動する必要があるためです。

このコードを見栄えよくするにはどうすればよいですか?

private void getUsersToDisplay() { 
    // Get users to display from firebase 
    Log.w(TAG, "User fetch initialized"); 

    DatabaseReference currentUserRef = mDatabase.getReference().child("users/" + mCurrentUser.getUid()); 

    // Get current user from firebase 
    currentUserRef.addListenerForSingleValueEvent(new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot currentUserSnapshot) { 
      // Get the users chosen location for use in distance calculation 
      final Double currentUserChosenLatitude = 
        Double.parseDouble(currentUserSnapshot.child("chosen_location/latlng/latitude").getValue().toString()); 
      final Double currentUserChosenLongitude = 
        Double.parseDouble(currentUserSnapshot.child("chosen_location/latlng/longitude").getValue().toString()); 

      DatabaseReference usersRef = mDatabase.getReference().child("users"); 

      // Get all users from firebase 
      usersRef.addListenerForSingleValueEvent(new ValueEventListener() { 
       @Override 
       public void onDataChange(DataSnapshot allUsersSnapshot) { 
        // For all users in firebase 
        for (DataSnapshot userSnap : allUsersSnapshot.getChildren()) { 
         String userId = userSnap.getKey(); 

         DatabaseReference userRef = mDatabase.getReference().child("users/" + userId); 

         // If the user isn't the current user 
         if (!userId.equals(mCurrentUser.getUid())) { 
          // Get the user's info from firebase 
          userRef.addListenerForSingleValueEvent(new ValueEventListener() { 
           @Override 
           public void onDataChange(DataSnapshot userSnapshot) { 
            Double userChosenLatitude = 
              Double.parseDouble(userSnapshot.child("chosen_location/latlng/latitude").getValue().toString()); 
            Double userChosenLongitude = 
              Double.parseDouble(userSnapshot.child("chosen_location/latlng/longitude").getValue().toString()); 

            float[] results = new float[1]; 
            Location.distanceBetween(
              currentUserChosenLatitude, 
              currentUserChosenLongitude, 
              userChosenLatitude, 
              userChosenLongitude, 
              results); 

            // If the user is within 10km of the current user, display it 
            if (results[0] < 10000) { 
             users.put(userSnapshot.getKey(), (String) userSnapshot.child("first_name").getValue()); 
             mUserAdapter.add((String) userSnapshot.child("first_name").getValue()); 
             Log.w(TAG, "User to display fetch complete"); 
            } 
           } 

           @Override 
           public void onCancelled(DatabaseError databaseError) { 
            Log.w(TAG, "User to display fetch cancelled"); 
           } 
          }); 
         } 
        } 
        Log.w(TAG, "Users fetch completed"); 
       } 

       @Override 
       public void onCancelled(DatabaseError databaseError) { 
        Log.w(TAG, "Users fetch cancelled"); 
       } 
      }); 
      Log.w(TAG, "Current user fetch complete"); 
     } 

     @Override 
     public void onCancelled(DatabaseError databaseError) { 
      Log.w(TAG, "Current user fetch cancelled"); 
     } 
    }); 
} 
+0

Anonymoususコールバックオブジェクトを作成するのではなく、 'ValueEventListener'オブジェクトを作成して' .addListenerForSingleValueEvent'に渡すことができます。 –

+0

はい、それらはすべて連続して起動する必要があるため、最初の '' ValueEventListener''には、 。私はそれが大きな違いになるとは思わない。 – Dockson

答えて

1

それが読みやすくするので、私はこのような私のコードを記述します。

onCreate() { 
    dataRef.addListenerForSingleValueEvent(new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot dataSnapshot) { 
      doSomething(dataSnapshot); 
      ... 
     } 
     ... 
    } 
} 

doSomething(DataSnapshot dataSnapshot) { 
    ... 
} 

私は別のFirebase呼び出しの後に実行するFirebaseコールをしたい場合は、私はdoSomething内に置きます。

しかし、その呼び出しは(とあなたのサンプルコードから、「すべてのユーザーを取得する」コール「現在のユーザーを取得する」のように)お互いの後に実行する必要はありません場合、私はこのようにそれを作った:

boolean firstCallDone = false; 
boolean secondCallDone = false; 

DataSnapshot firstDataSnapshot = null; 
DataSnapshot secondDataSnapshot = null; 

onCreate() { 
    firstRef.addListenerForSingleValueEvent(new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot dataSnapshot) { 
      firstCallDone = true; 
      firstDataSnapshot = dataSnapshot; 

      if (firsCallDone && secondCallDone) 
       doSomething(); 
     } 
     ... 
    } 
    secondRef.addListenerForSingleValueEvent(new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot dataSnapshot) { 
      secondCallDone = true; 
      secondDataSnapshot = dataSnapshot; 

      if (firsCallDone && secondCallDone) 
       doSomething(); 
     } 
     ... 
    } 
} 

doSomething() { 
    // do something with firstDataSnapshot and secondDataSnapshot 
    ... 
} 

このヘルプが必要です。

+0

はい、少し助けてくれます、ありがとう。 – Dockson

+0

質問に答えられない場合は、その理由を説明してください。あなたの質問は広すぎます – koceeng

関連する問題