浅谈Android中的BaseAdpater
16lz
2021-01-24
适配器(Adpater)在Android发开中占有非常重地位,你可以理解它是一个从“数据源”通向“视图控件”的桥梁,下面一张图非常直观的说明了“数据源”、“适配器”、“视图控件”三者间的关系
Android为我们提供了很多类型的适配器
从中可以看到,我们之前常用ArrayAdpater、SimpleAdpater等类型的适配器,都是继承于BaseAdapter。BaseAdapter是一个抽象类,我们在使用它的使用它的时候,需要自定义一个类继承它并重写它的一些方法,它的特点是具有较高的灵活性。这里我们还是用ListView来作为今天这个小例子的显示控件。 1.因为ListView中每一个Item都是一个视图,所以我们先新建一个Item的布局:
item.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="wrap_content"> <ImageView android:id="@+id/image" android:layout_width="60dp" android:layout_height="60dp" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/title" android:text="标题" android:textSize="25sp" android:gravity="center" android:layout_width="match_parent" android:layout_height="30dp" android:layout_toEndOf="@+id/image" /> <TextView android:id="@+id/text" android:text="内容" android:textSize="20sp" android:gravity="center_vertical" android:layout_width="match_parent" android:layout_height="30dp" android:layout_toEndOf="@+id/image" android:layout_below="@+id/title" />RelativeLayout>
效果:
2.创建一个ItemBean类,它抽象了Item中的所有控件对应的数据源
package com.example.baseadapter_test;/** * 将ListView要显示的Item抽象成一个类 */public class ItemBean { public int Item_ImageResId; public String Item_Title; public String Item_Text; public ItemBean(int Item_ImageResId,String Item_Tilie,String Item_Text) { this.Item_ImageResId = Item_ImageResId; this.Item_Text = Item_Text; this.Item_Title = Item_Tilie; } }
3.MainActivity
package com.example.baseadapter_test;import java.util.ArrayList;import java.util.List;import android.app.Activity;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;import android.widget.ListView;public class MainActivity extends Activity { private List itemBeansList = new ArrayList(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //创建数据源 for (int i = 0; i < 20; i++) { itemBeansList.add(new ItemBean(R.drawable.ic_launcher, "我是标题" + i, "我是内容容" + i)); } //初始化控件 ListView listView = (ListView)findViewById(R.id.listview); //设置适配器 listView.setAdapter(new MyAdapter(this, itemBeansList)); }}
4.自定义一个MyAdapter类继承BaseAdapter并重写它的一些方法:
package com.example.baseadapter_test;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;public class MAdpater extends BaseAdapter{ private List itemBeansList; //LayoutInflater作用是将layout的xml布局文件实例化为View类对象 private LayoutInflater inflater; public MyAdapter(Context context,List itemBeansList) { this.itemBeansList = itemBeansList; inflater = LayoutInflater.from(context); } /** * 返回数据的总数,它的值决定了ListView一共显示多少行 */ @Override public int getCount() { return itemBeansList.size(); } /** * 获取数据源中与指定索引对应的数据项 */ @Override public Object getItem(int position) { return itemBeansList.get(position); } /** * 获取在ListView中与指定索引对应的行id */ @Override public long getItemId(int position) { return position; } /** * 返回每个Item(每一行)的显示内容 */ @Override public View getView(int position, View convertView, ViewGroup parent) { return null; }}
今天的重点来了~~!!!这里我要重点的说一下public View getView(......)这个方法,它会直接影响到ListView的性能。 在这之前,我们必须先来了解一下ListView的工作原(摘自http://www.cnblogs.com/xiaowenji/archive/2010/12/08/1900579.html): 1.ListView 针对List中每个item,要求 adapter “给我一个视图” (getView)。 2.一个新的视图(被创建然后)被返回并显示 如果我们要显示很多个item,我们肯定不能一直通过重新创建View并返回,因为这样会极大的消耗内存!怎么办呢?Android中有个叫做Recycler的构件,用来缓存视图,下图是他的工作原理:
(1).如果你有10亿个项目(item),其中只有可见的项目存在内存中,其他的在Recycler中。 (2).ListView先请求一个type1视图(getView)然后请求其他可见的项目。convertView在getView中是空(null)的。 (3).当item1滚出屏幕,并且一个新的项目从屏幕低端上来时,ListView再请求一个type1视图。convertView此时不是空值了,它的值是item1。你只需设定新的数据然后返回convertView,不必重新创建一个视图。 了解了ListView缓存机制后,我们就开始愉快的重写public View getView(......)吧!|_( ̄▽ ̄)_|
重写方式一之“逗比式”:
@Override public View getView(int position, View convertView, ViewGroup parent) { //将布局文件转化成View对象 View view = inflater.inflate(R.layout.item, null); //在已创建的View查找控件 ImageView imageView = (ImageView)view.findViewById(R.id.image); TextView text = (TextView)view.findViewById(R.id.text); TextView title = (TextView)view.findViewById(R.id.title); //将数据添加到控件中 ItemBean bean = itemBeansList.get(position); imageView.setImageResource(bean.Item_ImageResId); text.setText(bean.Item_Text); title.setText(bean.Item_Title); return view; }
该方式通过不停的创建View并返回,没有利用到ListView的缓存机制,不但效率低,且非常浪费内存资源,如果你用这钟方式去做开发,我只想说你是个逗比!
重写方式一之“普通式”:
@Override public View getView(int position, View convertView, ViewGroup parent) { //判断convertView是否被缓存(如果已经被创建,就直接使用缓存的convertView,不需要重新创建convertView) if(convertView == null){ //实例化一个布局 convertView = inflater.inflate(R.layout.item, null); } ImageView imageView = (ImageView)convertView.findViewById(R.id.image); TextView text = (TextView)convertView.findViewById(R.id.text); TextView title = (TextView)convertView.findViewById(R.id.title); //将数据添加到控件中 ItemBean bean = itemBeansList.get(position); imageView.setImageResource(bean.Item_ImageResId); text.setText(bean.Item_Text); title.setText(bean.Item_Title); return convertView; }
该方式充分利用了ListView的缓存特性,极大提升了ListView的性能。。。唉哟~不错哦!
更多相关文章
- Android(安卓)Layout 布局
- LinearLayout中组件右对齐
- Android(Xamarin)之旅(三)
- android 机顶盒开发-----GridView
- Android属性动画上手实现各种动画效果,自定义动画,抛物线等
- Android(安卓)主流屏幕以及适配
- Android学习笔记17:中级视图组件DatePicker和TimePicker
- Android工具HierarchyViewer 代码导读
- Android(安卓)UI系列之3D星体旋转效果