0

I am developing my first Android app using Firebase and I love it. My question is, how should I go about fetching data from the Firebase database properly? I am a bit confused about fetching data once and then with that data fetch some more.

I am basically nesting 'OnCompleteListeners' one inside of another and this pattern disturbs me. Is there a better and more proper way?

Here is my current approach:

//This is a weather app, users can monitor different weather stations 

//We first get the weather stations that the current user owns:
// I used two collections in this approach, "ownership" permission is read only to the user
DocumentReference docRef = mDatabase.collection("ownership").document( mUser.getUid() );

docRef.get().addOnCompleteListener( new OnCompleteListener<DocumentSnapshot>() {

    @Override
    public void onComplete(@NonNull Task<DocumentSnapshot> task) {

        if ( task.isSuccessful() ) {

            DocumentSnapshot document = task.getResult();
            if ( document.exists() ) {

                Map<String, Object> data = document.getData();
                if ( data != null && data.containsKey("stations") ) {

                    // data is an string array, here is my ugly solution:
                    stationIds = data.get("stations").toString().replaceAll("[\\[\\]]", "").split(",");

                    if ( stationIds.length != 0 ) {

                        for ( int i = 0; i < stationIds.length; i++ ) {

                            // Now that I have the stations IDs I can get its data:
                            // !! the collection "stations" have read and write permission
                            // THIS PATTERN SEEMS VERY REDUNDANT!
                            DocumentReference docRef = mDatabase.collection("stations").document(stationIds[i]);
                            docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
                                @Override
                                public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                                    if (task.isSuccessful()) {
                                        DocumentSnapshot document = task.getResult();
                                        if (document.exists()) {
                                            Map<String, Object> data = document.getData();
                                            Log.d(TAG, "Document Snapshot: " + document.getData());

                                            if ( data != null && data.containsKey("name") ) {
                                                LinearLayout ll_root = MainActivity.this.findViewById(R.id.ll_station_list);

                                                LinearLayout ll_new = new LinearLayout(MainActivity.this);
                                                ll_new.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
                                                ll_new.setPadding(20,50,20,20);

                                                TextView tv_station_title = new TextView(MainActivity.this);
                                                tv_station_title.setText(data.get("name").toString());
                                                ll_new.addView( tv_station_title);
                                                ll_root.addView( ll_new );


                                                ll_new.setOnClickListener( new View.OnClickListener() {
                                                    @Override
                                                    public void onClick(View v) {
                                                        Intent intent = new Intent(MainActivity.this, LiveStation.class);
                                                        startActivity(intent);
                                                    }
                                                });
                                            }

                                        } else {
                                            Log.w(TAG, "Station not found");
                                        }
                                    } else {
                                        Log.w(TAG, "Unable to get station");
                                    }
                                }
                            });
                        }
                    }
                }

                Log.d( TAG, "Document Snapshot: " + document.getData() );

            } else {
                Log.w(TAG, "No document found");
            }
        } else {
            Log.w(TAG, "Get user stations failed: " + task.getException() );
        }
    }
});

I am not very familiar with async calls in Android. Usually I create a model that talks to the database and it can be called from anywhere in the app structure, but using Firebase it seems that I can't do that. It seems that every view requires its own unique calls to the database. Or maybe I got the whole idea wrong.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Caio Mar
  • 2,344
  • 5
  • 31
  • 37
  • Take a look **[here](https://stackoverflow.com/questions/47847694/how-to-return-datasnapshot-value-as-a-result-of-a-method/47853774)**, you can call `readData()` method everywhere you need in your activity. – Alex Mamo Jun 04 '18 at 14:39
  • The code looks pretty OK to me. If you don't like the levels of nesting, consider making your own simpler interface as the answer linked by Alex shows. Also have a look at this great blog post from fellow Firebaser Doug: https://medium.com/google-developers/why-are-firebase-apis-asynchronous-callbacks-promises-tasks-e037a6654a93. – Frank van Puffelen Jun 04 '18 at 14:48
  • It's been a few days working with Firebase and this concept makes more sense now. I was tempted on creating classes with global variables to make these properties 'retrievable' but it doesn't make sense, it disrupts the whole idea of asyncronism. I will keep doing what I am doing. Thanks for help and feedback! – Caio Mar Jun 06 '18 at 15:51

0 Answers0