2017-07-26 41 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