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) 其他
- ListView的Item布局中尽量避免半透明的元素:半透明的绘制比不透明更耗时
- 可以开启硬件加速
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