android中ListView的优化方案详解分析

Android中的ListView应该算是布局中几种最常用的组件之一了,使用也十分方便,我的上一篇博客讲了没有和优化的ListView,下面将介绍ListView几种比较常见的优化方法:

对于ListView的优化主要在自定义的Adapt中进行优化,其他的地方可优化的比较少,因此这几种不同的方案都是在对自定义的Adapt进行优化。

两个主要的布局文件和MainActivity.java

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.ecjtu.optimizationlistview.MainActivity" >

    <ListView android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/lv"></ListView>

</RelativeLayout>

mylayout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    
	<ImageView android:layout_height="match_parent"
	    android:layout_width="80dp"
	    android:id="@+id/image"
	    android:src="@drawable/ic_launcher"/>
	<TextView android:layout_width="match_parent"
	    android:layout_height="wrap_content"
	    android:id="@+id/title"
	    android:layout_toRightOf="@id/image"/>
	<TextView android:layout_width="match_parent"
	    android:layout_height="wrap_content"
	    android:id="@+id/content"
	    android:layout_below="@id/title"
	    android:layout_toRightOf="@id/image"/>
</RelativeLayout>

MainActivity.java

package com.ecjtu.optimizationlistview;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;

public class MainActivity extends Activity {
	private ListView listView;
	private List<Map<String, Object>> data;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		data = new ArrayList<>();
		listView = (ListView)findViewById(R.id.lv);
		for (int i = 1; i < 101; i++) {
			Map<String, Object> map = new HashMap<>();
			map.put("image", R.drawable.ic_launcher);
			map.put("title", "标题:"+i);
			map.put("content", "内容为:"+i);
			data.add(map);
		}//初始化数据
		
		listView.setAdapter(new MyAdapt(this,data));
	}

	
}


一 方案一

这种优化也是最普通的优化,优化力度比较低,我们注意到每次我们在执行getView方法是都是重新生成了一个View对象,而每次执行getView方法都要生成View,这样就没有很好的利用好View,因此我们想到的做法就是对view进行复用。

我们可以注意到在getView方法中提供了一个View对象ConvertView,经过测试我们可以发现,其实程序开始执行时,在ListView显示的所有项中的时候ConertView都为null,当对屏幕进行滑动(开始翻页)的时候并且第一行开始消失的时候,ConvertView开始不为null了,下面的图片就是这种情景:


当第一行被挤出去的时候,ConvertView会自动保存第一行的View对象以供下面的行使用,这样就可以利用这个来对其进行优化。代码如下:

package com.ecjtu.optimizationlistview;

import java.util.List;
import java.util.Map;

import android.content.Context;
import android.media.Image;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class MyAdapt extends BaseAdapter {
	private Context context;
	private List<Map<String, Object>> data;
	public MyAdapt(Context context,List<Map<String, Object>> data){
		this.context = context;
		this.data = data;
	}
	
	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return data.size();
	}

	@Override
	public Object getItem(int position) {
		// TODO Auto-generated method stub
		return data.get(position);
	}

	@Override
	public long getItemId(int position) {
		// TODO Auto-generated method stub
		return position;
	}
	
	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		// TODO Auto-generated method stub
		Map<String, Object> map = data.get(position);
		
		if (convertView==null) {
			convertView = View.inflate(context, R.layout.mylayout, null);
		}
		ImageView imageView = (ImageView) convertView.findViewById(R.id.image);
		TextView title = (TextView)convertView.findViewById(R.id.title);
		TextView content = (TextView)convertView.findViewById(R.id.content);
		imageView.setImageResource((Integer)map.get("image"));
		title.setText((String)map.get("title"));
		content.setText((String)map.get("content"));
		return convertView;
	}
	
}

二 方案二

对于上种优化方案,我们可以发现imageView、title、content还是要重复查找,想象一下要是如果组件多的话也是挺费事的,如果我们可以让view内的组件也随着view的复用而复用,那该是多美好的一件事啊。实际上谷歌官方也推荐了一种做法,就是把view中的组件构建成一个静态类的属性,这样就能对其进行重复利用。

静态类:

static class ViewHold{
		ImageView imageView;
		TextView title;
		TextView content;
	}

那么这个viewHolder类我们要如何使用才可以达到复用效果呢?基本思路就是在convertView为null的时候,我们不仅重新inflate出来一个view,并且还需要进行findviewbyId的查找工作,但是同时我们还需要获取一个ViewHolder类的对象,并将findviewById的结果赋值给ViewHolder中对应的成员变量。最后将holder对象与该view对象“绑”在一块。当convertView不为null时,我们直接使用converView,同时取出这个converView对应的holder对象,就获得了这个converView对象中的各个组件,它就是holder中的成员变量,这样在复用的时候,我们就不需要再去findViewById了,只需要在最开始的时候进行数次查找工作就可以了。这里的关键在于如何将view与holder对象进行绑定,那么就需要用到两个方法:setTag和getTag方法了:

整合MyAdapt后的代码为:

package com.ecjtu.optimizationlistview;

import java.util.List;
import java.util.Map;

import android.content.Context;
import android.media.Image;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class MyAdapt extends BaseAdapter {
	private Context context;
	private List<Map<String, Object>> data;
	public MyAdapt(Context context,List<Map<String, Object>> data){
		this.context = context;
		this.data = data;
	}
	
	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return data.size();
	}

	@Override
	public Object getItem(int position) {
		// TODO Auto-generated method stub
		return data.get(position);
	}

	@Override
	public long getItemId(int position) {
		// TODO Auto-generated method stub
		return position;
	}
	
	ViewHold viewHold;
	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		// TODO Auto-generated method stub
		Map<String, Object> map = data.get(position);
		if (convertView==null) {
			convertView = View.inflate(context, R.layout.mylayout, null);
			viewHold = new ViewHold();
			viewHold.imageView = (ImageView) convertView.findViewById(R.id.image);
			viewHold.title = (TextView) convertView.findViewById(R.id.title);
			viewHold.content = (TextView) convertView.findViewById(R.id.content);
			convertView.setTag(viewHold);//将viewHold加入到convertView中进行存储,以便后面使用
		}else {
			viewHold = (ViewHold) convertView.getTag();//直接从convertView取出使用
		}
		viewHold.imageView.setImageResource((Integer)map.get("image"));
		viewHold.title.setText((String)map.get("title"));
		viewHold.content.setText((String)map.get("content"));
		/*if (convertView==null) {
			convertView = View.inflate(context, R.layout.mylayout, null);
		}
		ImageView imageView = (ImageView) convertView.findViewById(R.id.image);
		TextView title = (TextView)convertView.findViewById(R.id.title);
		TextView content = (TextView)convertView.findViewById(R.id.content);
		imageView.setImageResource((Integer)map.get("image"));
		title.setText((String)map.get("title"));
		content.setText((String)map.get("content"));*/
		return convertView;
	}
	//静态类,属性为view中的组件
	static class ViewHold{
		ImageView imageView;
		TextView title;
		TextView content;
	}
}


结果图:




  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值