2017-07-26 118 views
0

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

类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() { 

} 

}

回答

3

所有的网络互动等工作火力地堡客户确实已经发生过主线程。主线程上发生的唯一情况是回调代码,例如onChildAdded()。这样做是为了您可以从该代码更新您的用户界面。

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

如果您确实必须检索并解码很多项目,则需要使用AsyncTaskbackground service。如果您在制作这些工作时遇到问题,请分享minimal code that reproduces where you got stuck

+0

我已经尝试了asyncTask中的代码,并且我甚至使用了辅助数组,并且一旦加载了所有元素都将加载辅助数据到主数组中但它仍然处于冻结状态 – Benkasem

+0

所有对'dataSnapshot.getValue(Model.class )'仍然在主线程上发生。为了防止这种情况,您需要在'onChildAdded()'回调内创建后台任务**。做7000次也不容易,所以我建议使用后台服务来卸载工作。尽管如此,最好的解决方案仍然是一样的:不要求提供7000个物品,或者至少一次。 –

+0

我将听众放入服务中吗?或者我必须在OnChildAdded – Benkasem

0

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

+0

我试过了,它没有解决,谢谢 – Benkasem

+0

好的,请告诉我你的代码。 –

+0

我编辑了有问题的代码 – Benkasem