您的位置:首页 > 移动开发 > Android开发

Android学习历程14-Android ListView优化

2016-02-23 19:02 615 查看

列表的显示需要三个元素:

ListVeiw: 用来展示列表的View。

适配器 : 用来把数据映射到ListView上

数据: 具体的将被映射的字符串,图片,或者基本组件。

ListView的工作原理如下:

  ListView 针对每个item,要求 adapter “返回一个视图” (getView),也就是说ListView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到ListView的长度,然后根据这个长度,调用getView()一行一行的绘制ListView的每一项。如果你的getCount()返回值是0的话,列表一行都不会显示,如果返回1,就只显示一行。返回几则显示几行。如果我们有几千几万甚至更多的item要显示怎么办?为每个Item创建一个新的View?不可能!!!实际上Android早已经缓存了这些视图,大家可以看下下面这个截图来理解下,这个图是解释ListView工作原理的最经典的图了大家可以收藏下,不懂的时候拿来看看,加深理解,其实Android中有个叫做Recycler的构件,顺带列举下与Recycler相关的已经由Google做过N多优化过的东东比如:AbsListView.RecyclerListener、ViewDebug.RecyclerTraceType等等,要了解的朋友自己查下,不难理解,下图是ListView加载数据的工作原理(原理图看不清楚的点击后看大图):

  


下面简单说下上图的原理:

如果你有几千几万甚至更多的选项(item)时,其中只有可见的项目存在内存(内存内存哦,说的优化就是说在内存中的优化!!!)中,其他的在Recycler中

ListView先请求一个type1视图(getView)然后请求其他可见的项目。convertView在getView中是空(null)的

当item1滚出屏幕,并且一个新的项目从屏幕低端上来时,ListView再请求一个type1视图。convertView此时不是空值了,它的值是item1。你只需设定新的数据然后返回convertView,不必重新创建一个视图

ListView的优化:

(前两点都是利用ListView的自身优化机制优化【缓存优化】)

1.利用ListView自身的缓存机制,他会缓存条目中的一个条目item,当listview第一屏显示完成之后,就会出现一个缓存条目,其实就是BaseAdapter里面的public View getView(int position, View convertView, ViewGroup parent)。

2.减少findViewById()的次数,findViewById是一个相对比较耗性能的操作,因为这个操作每次都需要到布局中去查找文件。把item里面的控件封装成一个javaBean,当item条目被加载的时候就去找到对应的控件。

3.利用时间去换取时间,比如开机优化,把一些重要的程序先启动了,启动完系统之后再启动其他程序。

4.利用空间去换取时间,把要获取的数据先加载到内存里面,再处理数据的时候,直接从内存中获取。

直接附上源代码

MainActivity中的代码

package com.example.androidlistview;
import java.util.ArrayList;
import java.util.HashMap;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

private ListView lv;
//定义一个动态数组
ArrayList<HashMap<String, Object>> listItem;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

lv = (ListView) findViewById(R.id.lv);
MyAdapter mAdapter = new MyAdapter(this);//得到一个MyAdapter对象
lv.setAdapter(mAdapter);//为ListView绑定Adapter
/**为ListView添加点击事件*/
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
Toast.makeText(MainActivity.this, "你点击了ListView条目" + arg2, Toast.LENGTH_LONG).show();
}
});
}
/**添加一个得到数据的方法,方便使用*/
private ArrayList<HashMap<String, Object>> getDate(){
listItem = new ArrayList<HashMap<String,Object>>();
/**为动态数组添加数据*/
for(int i=0;i<30;i++)
{
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("ItemTitle", "第"+i+"行");
map.put("ItemText", "这是第"+i+"行");
listItem.add(map);
}
return listItem;
}
/** 新建一个类继承BaseAdapter,实现视图与数据的绑定
*/
private class MyAdapter extends BaseAdapter {
private LayoutInflater mInflater;//得到一个LayoutInfalter对象用来导入布局

/**构造函数*/
public MyAdapter(Context context) {
this.mInflater = LayoutInflater.from(context);
}

@Override
public int getCount() {
return getDate().size();//返回数组的长度
}

@Override
public Object getItem(int position) {
return null;
}

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

/**书中详细解释该方法*/
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
//观察convertView随ListView滚动情况
Log.v("MyListViewBase", "getView " + position + " " + convertView);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.listview_item,null);
holder = new ViewHolder();
/**得到各个控件的对象*/
holder.title = (TextView) convertView.findViewById(R.id.ItemTitle);
holder.text = (TextView) convertView.findViewById(R.id.ItemText);
holder.bt = (Button) convertView.findViewById(R.id.ItemButton);
convertView.setTag(holder);//绑定ViewHolder对象
}
else{
holder = (ViewHolder)convertView.getTag();//取出ViewHolder对象
}
/**设置TextView显示的内容,即我们存放在动态数组中的数据*/
holder.title.setText(getDate().get(position).get("ItemTitle").toString());
holder.text.setText(getDate().get(position).get("ItemText").toString());

/**为Button添加点击事件*/
holder.bt.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "你点击了按钮" + position, Toast.LENGTH_LONG).show();
}
});

return convertView;
}

}

/**存放控件*/
public final class ViewHolder{
public TextView title;
public TextView text;
public Button   bt;
}
}


activity_main 布局文件的代码

<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">

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

</RelativeLayout>


listview_item中的布局代码

<?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="60dp"
android:orientation="horizontal" >

<LinearLayout
android:layout_height="match_parent"
android:layout_weight="7"
android:layout_width="0dp"
android:orientation="vertical">

<TextView
android:id="@+id/ItemTitle"
android:layout_weight="1"
android:layout_height="0dp"
android:layout_width="wrap_content"
android:text="姓名"/>

<TextView
android:id="@+id/ItemText"
android:layout_weight="1"
android:layout_height="0dp"
android:layout_width="wrap_content"
android:text="年龄"/>
</LinearLayout>

<Button
android:id="@+id/ItemButton"
android:layout_weight="1"
android:layout_height="match_parent"
android:layout_width="0dp"
android:text="Click"
android:focusable="false"/>

</LinearLayout>


运行界面如图所示:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: