2016-04-08 11 views
2

概要:私はチャットアプリケーションを持っています。今までは、リスト内のチャットアイテムをロードするために、ListViewと共にCursorAdapterを使用していました。しかし今、私はRecyclerViewをRecyclerView.Adapterで使用するコードとwhatsappのような "Load More"機能を使用するコードをリファクタリングする予定です。RecyclerView.Adapterのアイテムが多数あります - メモリの問題

問題:メモリ消費。 CursorAdapterでは、可視領域にないアイテムがガベージコレクションされましたが、今度はCustomModalのArrayListを使用しているので、リスト内のすべてのアイテムをロードすると([Load More]ボタンをクリックして)表示していますメモリログで高いメモリ消費量(ガベージコレクションなし)。

私の推測は今、私はArrayList内のすべての項目を読み込んでいて、それが問題の原因です。それですか?

問題を回避したり、問題を最適化する方法はありますか?

EDIT: は、ここに完全なコードをポストが、ここで私が実装しましたアダプタの種類の抜粋であることはできません。

public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.MyViewHolder> { 

    private ArrayList<MyModal> mMyModals; 

    public MessageAdapter(ArrayList<MyModal> mMyModals) { 
     this.mMyModals = mMyModals; 
     //... Some fields initialization here 
    } 

    public void changeList(ArrayList<MyModal> myModals, boolean isLoadMoreEnabled){ 
     this.mMyModals = myModals; 
     //... Some fields initialization here 
     notifyDataSetChanged(); 
    } 

    public void toggleLoadMore(boolean isLoadMoreEnabled){ 
     if(isLoadMoreEnabled){ 
      //..Checks if load more is already enabled or not 
      //..If not then enables it by adding an item at 0th poition of MyModal list 
      //..Then notifyDataSetChanged() 
     }else{ 
      //..Checks if load more is already disabled or not 
      //..If not then disables it by removing an item at 0th poition of MyModal list 
      //..Then notifyDataSetChanged() 
     } 
    } 

    @Override 
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     MyViewHolder messageViewHolder = null; 
     View itemLayoutView = null; 

     MyModal.MessageType messageType = MyModal.MessageType.getMessageTypeFromValue(viewType); 
     switch (messageType){ 
      case MESSAGE_TYPE1: 
       itemLayoutView = LayoutInflater.from(parent.getContext()) 
         .inflate(R.layout.layout1, null); 
       messageViewHolder = new Type1ViewHolder(itemLayoutView); 
       break; 
      case MESSAGE_TYPE2: 
       itemLayoutView = LayoutInflater.from(parent.getContext()) 
         .inflate(R.layout.layout2, null); 
       messageViewHolder = new Type2ViewHolder(itemLayoutView); 
       break; 
     } 

     return messageViewHolder; 
    } 

    @Override 
    public void onBindViewHolder(MyViewHolder holder, int position) { 
     final MyModal myModal = mMyModals.get(position); 
     MyModal.MessageType messageType = myModal.getMessageType(); 
     holder.initialize(myModal); 
    } 

    @Override 
    public int getItemCount() { 
     return (mMyModals != null)?mMyModals.size():0; 
    } 

    @Override 
    public int getItemViewType(int position) { 
     return mMyModals.get(position).getMessageType().getValue(); 
    } 

    public abstract class MyViewHolder extends RecyclerView.ViewHolder { 

     public MyViewHolder(View itemLayoutView) { 
      super(itemLayoutView); 
     } 

     public abstract void initialize(MyModal myModal); 
    } 

    class Type1ViewHolder extends MyViewHolder { 

     //...Variables 

     public Type1ViewHolder(View itemLayoutView) { 
      super(itemLayoutView); 
      //...variables initialization here 
     } 

     @Override 
     public void initialize(MyModal myModal) { 
      //...Setting values in view using myModal 
     } 
    } 

    class Type2ViewHolder extends MyViewHolder { 

     //...Variables 

     public TextViewHolder(View itemLayoutView) { 
      super(itemLayoutView); 
      //...variables initialization here 
     } 

     @Override 
     public void initialize(MyModal myModal) { 
      //...Setting values in view using myModal 
     } 
    } 
} 
+0

アダプタクラスを表示できますか?必要以上に多くの時間を過ごしているかもしれません。あなたがコードを投稿したら、一度チェックしてください –

+0

ちょっとRagesh、私はコードで私の質問を更新しました。ここで問題を理解するのを助けてくれますか? – Wanted

答えて

1

まず第一に:ここで

public void changeList(ArrayList<MyModal> myModals, boolean isLoadMoreEnabled){ 
    this.mMyModals = myModals; 
    //... Some fields initialization here 
    notifyDataSetChanged(); 
} 

あなたが新しいのArrayListを作成し、あなたのmMyModalsに割り当てています。これは、この時点で2人のarraylistsが存在し、必要なスペース量の2倍を占めることを意味します。 GCは期待通りの動作をしません。 arraylistはあなたの活動の中で初期化されているので、arraylistが存続する限り持続し、初期のarraylistも持続します。

あなたのアクティビティに新しいarraylistを作成し、それをchangeListに渡す代わりに。ちょうどあなたの古いのArrayListをクリアして、あなたは以下の

 public void changeList(ArrayList<MyModal> myModals, boolean isLoadMoreEnabled){ 
    this.mMyModals.clear(); 
    this.mMyModels.addAll(myModels); 
    //... Some fields initialization here 
    notifyDataSetChanged(); 
} 

iが明確でないです場合は私に知らせてください行うことができ、アダプタチェンジの方法でもthat.Andを渡します。これが機能しない場合は、アクティビティコードも表示してください。

+0

ありがとう@Ragesh、明日それを試してみましょう。 – Wanted

+0

その(clear()とaddAll()メソッド)が実際に動作しました。少なくともGCはそれを今すぐ行うことができます。再度、感謝します。 – Wanted

+0

それからそれを正しいものとしてマークしてください。 –

1

代わりの全体ArrayListを交換し、 notifyDataSetChangedに電話をかけ、項目をArrayListに追加してからnotifyItemRangeInserted(int positionStart, int itemCount)に電話してください。おそらくそれが機能する可能性があります。また、AdapterArrayListを置き換える必要はありません。 Activity/FragmentはおそらくArrayListと同じですが、Activity/Fragmentでこのリストを編集してから、notifyItemRangeInserted(int positionStart, int itemCount)に電話するとこのトリックを行う必要があります。また、すべてのメッセージを取得するのではなく、次のX個のメッセージだけを取得することもできます。既に取得していない場合は、以前に取得したメッセージは取得しません。

+0

ありがとうございますJeffalee、それを試してみましょう。しかし、私がarraylist参照に新しいオブジェクトを割り当てる場合、古いオブジェクトはGCの対象となります。しかし、私はそれを見ていない。私のアプリは完全な128Mbのメモリを消費しています – Wanted