AndroidAndroid开发经验谈Android技术知识

ListView 缓存

2019-11-08  本文已影响0人  瑟闻风倾

ListView:ListView是一个能够将数据集合以动态滚动的方式展示到用户界面上的View。

1. ListView的适配器模式

适配器模式.png
说明:ListView的适配器模式将数据资源和视图分离,通过适配器来连接两者,属于MVC模式。

2. ListView的垃圾回收机制RecycleBin

RecycleBin机制.png
说明:适配器的getCount()方法用来计算数据资源的长度,有n条数据就会调用n次getView()方法来绘制Item,当数据长度很多时,ListView的recycleBin机制(内存回收机制)保证滑动时不会发生OOM(内存泄漏)。
如:一旦Item0划出屏幕,则Item0就会被放到RecycleBin机制里,在Item6要显示的时候再从缓存中获取到缓存的Item0,达到复用的目的。recycleBin机制保证了仅界面内显示的数据会存储在内存,故列表滑动时不会造成内存泄漏

3. ListView的优化

(1) convertView复用和viewHolder

//绘制ListView的每个Item
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder;
            if (convertView == null){
                viewHolder = new ViewHolder();
                convertView = LayoutInflater.from(ListViewTestActivity.this).inflate(R.layout.item_listview,null);
                viewHolder.title = convertView.findViewById(R.id.title);
                viewHolder.content= convertView.findViewById(R.id.content);
                convertView.setTag(viewHolder);
            }else {
                viewHolder = (ViewHolder)convertView.getTag();
            }
            viewHolder.title.setText("标题");
            viewHolder.info.setText("内容");
            return convertView;
        }

        class ViewHolder{
            private TextView title;
            private TextView content;
        }

convertView是ListView优化最重要的一点:convertView其实是缓存的作用。利用缓存convertView来做判断,当缓存中convertView为空时才创建相应的View,存在则调用已有的View,从而提升了性能
自定义viewHolder:View是一个二叉树的结构,每次遍历都很耗时,利用viewHolder可以减少每次findViewById()的调用次数,从而在时间上进行优化。
(2) 三级缓存和监听滑动事件
三级缓存:图片加载时需要用到缓存机制来进行。
监听滑动事件:尽量不要在getView()中做耗时操作,保证ListView滑动的流畅性,避免滑动时卡顿。如果一定要在ListView滑动时加载,可以设置ListView的监听事件,当滑动停止时再去加载整个图片。
(3) 其他

4. ListView使用

(1) ListViewTestActivity.java

package comi.example.liy.mytestdemo;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;

/**
 * Created by liy on 2019-11-08 15:38
 */
public class ListViewTestActivity extends AppCompatActivity {

    private ListView listView;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_listview);
        listView = findViewById(R.id.listview);
        listView.setAdapter(new MyAdapter(this));
    }

    class MyAdapter extends BaseAdapter{
        private Context context;
        private ArrayList<NewsInfo> newsInfos = new ArrayList<>();

        public MyAdapter(Context context) {
            this.context = context;
            newsInfos = new NewsInfo().getNewsInfos();
        }

        //计算数据资源的长度:有n条数据就会调用n次getView()方法来绘制Item,当数据长度很多时,ListView的recycleBin机制(内存回收机制)保证滑动时不会发生OOM(内存泄漏)
        @Override
        public int getCount() {
            if (newsInfos == null){
                return 0;
            }
            return newsInfos.size();
        }

        @Override
        public Object getItem(int position) {
            return newsInfos.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        //绘制ListView的每个Item
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder;
            if (convertView == null){
                convertView = LayoutInflater.from(ListViewTestActivity.this).inflate(R.layout.item_listview,null);
                viewHolder = new ViewHolder();
                viewHolder.title = convertView.findViewById(R.id.title);
                viewHolder.content = convertView.findViewById(R.id.content);
                convertView.setTag(viewHolder);
            }else {
                viewHolder = (ViewHolder)convertView.getTag();
            }
            viewHolder.title.setText(newsInfos.get(position).getTitle());
            viewHolder.content.setText(newsInfos.get(position).getContent());
            return convertView;
        }

        class ViewHolder{
            private TextView title;
            private TextView content;
        }
    }

}

(2) NewsInfo.java

package comi.example.liy.mytestdemo;

import java.util.ArrayList;

/**
 * Created by liy on 2019-11-08 15:54
 */
public class NewsInfo {
    private String title;
    private String content;

    public NewsInfo() {

    }

    public NewsInfo(String title, String content) {
        this.title = title;
        this.content= content;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    //创建测试数据
    public ArrayList<NewsInfo> getNewsInfos(){
        ArrayList<NewsInfo> newsInfos = new ArrayList<>();
        newsInfos.add(new NewsInfo("标题1","信息内容1"));
        newsInfos.add(new NewsInfo("标题2","信息内容2"));
        newsInfos.add(new NewsInfo("标题3","信息内容3"));
        newsInfos.add(new NewsInfo("标题4","信息内容4"));
        newsInfos.add(new NewsInfo("标题5","信息内容5"));
        newsInfos.add(new NewsInfo("标题6","信息内容6"));
        newsInfos.add(new NewsInfo("标题7","信息内容7"));
        newsInfos.add(new NewsInfo("标题8","信息内容8"));
        newsInfos.add(new NewsInfo("标题9","信息内容9"));
        newsInfos.add(new NewsInfo("标题10","信息内容10"));
        return newsInfos;
    }

}

(3) activity_listview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </ListView>
</LinearLayout>

(4) item_listview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.v7.widget.LinearLayoutCompat
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/title"
            android:textSize="20sp"/>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/content"
            android:textSize="16sp"/>
    </android.support.v7.widget.LinearLayoutCompat>
</LinearLayout>

(5) 运行效果


运行效果.png

拓展实现ListView的横向滑动可置顶或删除列表项

上一篇下一篇

猜你喜欢

热点阅读