android:Listview和recycleview的内存优化原理

deoy1644 7年前
   <p>吐槽:一直想写一篇完整的,能系统地介绍某个知识点的文章,但由于技术不够加上懒,只能仰望其他大神写出的非常优秀的文章,从中学习一二。今天看了hongyang大神写的关于recycleview的博客,获益良多啊!不过鸿神可能要全面解析这个控件,没那么多篇幅来写一些原理问题,所以我google了一番结合listview来介绍他们的优化原理(作为初学者,我仅凭自己理解去写这篇文章,如有错误,你来打我啊(开玩笑...),还是非常希望各位能及时帮我更正)</p>    <p>首先我们来看下,没有优化过的listview中getView方法(因为是介绍原理问题,所有的代码就不贴上了,百度一大堆)</p>    <pre>  <code class="language-java">@Override          public View getView(int position, View convertView, ViewGroup parent) {              //listview_item里只有一个textview              View view = View.inflate(MainActivity.this, R.layout.listview_item,                      null);              //使用每一次都findviewById的方法来获得listview_item内部的组件              TextView tv_item = (TextView) view.findViewById(R.id.tv_item);              tv_item.setText(list.get(position));              return view;          }</code></pre>    <p>当我们的item有十几个的时候,手机屏幕不足以完全显示(说iphone18的走开!!),所以我们要向上滑动以显示下面其他的item,但这时前面的item就会淡出屏幕,再向下滑动,又显示前面的item了,但你会发现,无论显示第一个item还是显示最后一个item,只要出现在屏幕上一次,就会调用一次getView来创建这个item。这无疑是很浪费内存的,所以就有下面的优化方案。</p>    <pre>  <code class="language-java">public View getView(int position, View convertView, ViewGroup parent) {              View view;              ViewHolder holder;              // 判断convertView的状态,来达到复用效果              if (null == convertView) {                  // 如果convertView为空,则表示第一次显示该条目,需要创建一个view                  view = View.inflate(MainActivity.this, R.layout.listview_item,                          null);                  //新建一个viewholder对象                  holder = new ViewHolder();                  //将findviewbyID的结果赋值给holder对应的成员变量                  holder.tvHolder = (TextView) view.findViewById(R.id.tv_item);                  // 将holder与view进行绑定                  view.setTag(holder);              } else {                  // 否则表示可以复用convertView                  view = convertView;                  holder = (ViewHolder) view.getTag();              }              // 直接操作holder中的成员变量即可,不需要每次都findViewById              holder.tvHolder.setText(list.get(position));              return view;          }</code></pre>    <p>convertView这个参数设计非常巧妙,是用来储存那些被你万恶的手指滑动导致淡出的item,当它为空,说明之前没有被创建过,所以就创建这个item,它不为空时,嘿嘿,说明是被淡出的item,之前有被创建,那就直接拿出来用就行啦。关于ViewHolder很多资料也有介绍,这里也不再赘述了。来看下图更有利于理解:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/dd3756ef6bf38e14b2e8d63c877b8c50.png"></p>    <p>Paste_Image.png</p>    <p>上面是ListView的。接下来我们来看下RecycleView:</p>    <pre>  <code class="language-java">package com.example.q_recycler;    import android.support.v7.widget.RecyclerView;  import android.view.LayoutInflater;  import android.view.View;  import android.view.ViewGroup;  import android.widget.LinearLayout;  import android.widget.TextView;    import java.util.List;    /**   * Created by 强强 on 2017/2/6.   */    public class MyRecycleviewAdapter extends RecyclerView.Adapter<MyRecycleviewAdapter.ViewHolder>{        List<String> list;        public MyRecycleviewAdapter(List<String> list){          this.list=list;      }        @Override      public MyRecycleviewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {          View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.id_num,parent,false);          return new ViewHolder(view);      }        @Override      public void onBindViewHolder(ViewHolder holder, int position) {          holder.tv.setText(list.get(position));      }        @Override      public int getItemCount() {          if(list!=null) return list.size();          else              return 0;      }         class ViewHolder extends RecyclerView.ViewHolder {         public TextView tv;          public ViewHolder(View itemView) {              super(itemView);              tv= (TextView) itemView.findViewById(R.id.id_num);          }      }  }</code></pre>    <p>RecycleView作为ListView的升级版,自然有它的优势,抛弃那n多的功能(被鸿神称为艺术般的控件),它的内存优化也是独到的哦。</p>    <p>我的理解是:RecycleView提供了一个缓存机制,当一个item没有被创建时,就会调用onCreateViewHolder的方法创建这个item,同时也放入到缓存中,以ViewHolder的形式返回,当要显示item时,就会在缓存中寻找有没有创建过这个item,如果创建了的话就直接调用onBindViewHolder方法进行渲染显示。这里也避免重复创建item了,可见,它们的优化原理是相差无几的,结合起来更能让人理解。</p>    <p> </p>    <p> </p>    <p> </p>    <p>来自:http://www.jianshu.com/p/3b391cb69c1b</p>    <p> </p>