2017-07-26 9 views
0

Myアプリケーションは、ArrayList(約7000項目)にデータを読み込むためにChildEventListenerを実装しています。 各アイテムのchildAdded実行中、インターフェイスは完全にフリーズし、使用できません。 バックグラウンドで実行する方法はありますか?それはユーザビリティを損なわないでしょうか? 私は既にAsyncTaskとスレッドを使ってみましたが、とにかくアプリケーションがフリーズします。前もって感謝します。Firebase Listener freezes app ui

クラス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

すべてのネットワーク相互作用およびFirebaseクライアントが既にメインスレッドをオフに発生しない他の作業を拡張します。メインスレッドで発生する唯一の事柄は、コードへのコールバックです(onChildAdded()など)。これは、そのコードからUIを更新できるように行われます。

私の推測では、dataSnapshot.getValue(Model.class) 7000回の呼び出しには時間がかかり過ぎるため、フレームがスキップされている可能性があります。本当に7000モデルが必要ですか?通常は、ユーザーに直接表示するデータのみを取得することをお勧めします.7000モデルは、ほとんどのAndroid搭載端末で画面に合理的に収まるほど多くの音を鳴らします。

実際に多くのアイテムを取得してデコードする必要がある場合は、AsyncTaskまたはbackground 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