Firebase Listener会冻结app ui

时间:2017-07-26 04:21:35

标签: android firebase firebase-realtime-database

我的应用实现了一个ChildEventListener来将数据加载到ArrayList(大约7000个项目)。 在每个项目的childAdded执行期间,界面完全冻结,无法使用。 有没有办法在后台运行它并且不会影响可用性? 我已经尝试过使用AsyncTask和一个Thread但是应用程序仍会冻结。提前谢谢。

类FBTask扩展了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() {

}

}

2 个答案:

答案 0 :(得分:3)

Firebase客户端所做的所有网络交互和其他工作都已经发生在主线程之外。在主线程上发生的唯一事情是对代码的回调,例如onChildAdded()。这样做是为了让您可以从该代码更新UI。

我的猜测是,调用dataSnapshot.getValue(Model.class) 7000次会花费太多时间,这会导致跳过帧。你真的需要7000款?我通常建议只检索您要直接向用户显示的数据,并且对于大多数Android设备而言,7000个模型听起来比在屏幕上更合理。

如果您真的必须检索并解码那么多项,则需要使用AsyncTaskbackground service。如果您无法完成这些工作,请分享minimal code that reproduces where you got stuck

答案 1 :(得分:0)

每个回调都由主线程(UI线程)处理。因为您有大量项目(7000项),所以有数组创建,从较小到大数组列表的项目副本在运行时发生。这导致ANR(冻结你的应用程序)。为避免这种情况,您可以简单地使用新线程在数组列表中添加项目。当你完成添加所有项目时,进行线程间通信(通知主线程),以便主线程做进一步的工作。这是确切的解决方案。我过去曾解决过类似的问题。