Benkasem
Benkasem

Reputation: 1

Firebase Listener freezes app ui

My app implements a ChildEventListener to load the data into an ArrayList (approximately 7000 items). During childAdded execution for each item, the interface freezes completely and can not be used. Is there any way to run it in the background and that does not impair usability? I've already tried using an AsyncTask and a Thread but the app freezes anyway. Thanks in advance.

class FBTask extends AsyncTas {

@Override
protected Boolean doInBackground(final Boolean... params){
    int size = 7000; //aprox,
    final ArrayList<Model> aux = new ArrayList<>();
    Query db = FirebaseDatabase.getInstance().getReference()
            .child("List").orderByChild("Double");
    ChildEventListener cEL = new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {
            Model x = dataSnapshot.getValue(Model.class);
            if(x.getT()!=null) {
                aux.add(x)
                Log.i("onChildAdded", x.getId() + " Added, pos: " + dX.size());
                if(aux.size()>=size) {
                    data = aux;
                }
            }
        }

        @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) {

        }
    };
    db.addChildEventListener(cEL);
}

@Override
protected void onProgressUpdate(Boolean... values) {

}

@Override
protected void onPreExecute() {

}

@Override
protected void onPostExecute(DownAdapter result) {
    if(result != null) {
        DownActivity.downRecView.setAdapter(result);
    }
}

@Override
protected void onCancelled() {

}

}

Upvotes: 0

Views: 1867

Answers (2)

Uddhav P. Gautam
Uddhav P. Gautam

Reputation: 7636

Every callbacks are handled by your Main Thread ( UI thread). Because you have large number of items (7000 items), there is array creation, copy of items from smaller to large array list is happening in runtime. This is causing ANR ( freeze your app). To avoid this, you can simply use new thread to add items in the array list. when you complete adding all items, do inter thread communication ( notify main thread) so that main thread does the further work. This is the exact solution. I had solved in the past the similar problem.

Upvotes: 0

Frank van Puffelen
Frank van Puffelen

Reputation: 599746

All network interaction and other work the Firebase client does already happens off the main thread. The only things that happens on the main thread are callbacks to your code, such onChildAdded(). This is done so you can update your UI from that code.

My guess is that calling dataSnapshot.getValue(Model.class) 7000 times is taking too much times, which is causing frames to be skipped. Do you really need 7000 models? I'd normally recommend to only retrieve data that you're going to show directly to the user, and 7000 models sounds like more than could reasonably fit on screen for most Android devices.

If you really must retrieve and decode that many items, you will need to use a AsyncTask or a background service. If you're having trouble making those work, share the minimal code that reproduces where you got stuck.

Upvotes: 3

Related Questions