`
come_for_dream
  • 浏览: 116610 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

ListView之BaseAdapter的使用

 
阅读更多

                                       Android杂谈--ListView之BaseAdapter的使用

  

      在上篇的文章中自己写了几个关于LisetView的几种使用方法,最后写了一个关于SimpleAdapter的Demo看了看SimpleAdapter的源码发现它继承了BaseAdapter的类,之前写的音乐播放器中也有关ListView+BaseAdapter的使用下面我针对BaseAdapter的使用进行一下简单的总结。在网上发现的一片文章写的不错就顺便用了,毕竟天下文章一大抄嘛。

///////////////////////////////////********转载内容*****////////////////////////////////////////////////

      话说开发用了各种Adapter之后感觉用的最舒服的还是BaseAdapter,尽管使用起来比其他适配器有些麻烦,但是使用它却能实现很多自己喜 欢的列表布局,比如ListView、GridView、Gallery、Spinner等等。它是直接继承自接口类Adapter的,使用 BaseAdapter时需要重写很多方法,其中最重要的当属getView,因为这会涉及到ListView优化等问题,其他的方法可以参考链接的文章

BaseAdapter与其他Adapter有些不一样,其他的Adapter可以直接在其构造方法中进行数据的设置,比如

SimpleAdapter adapter = new SimpleAdapter(this, getData(), R.layout.list_item, new String[]{"img","title","info",new int[]{R.id.img, R.id.title, R.id.info}});

但是在BaseAdapter中需要实现一个继承自BaseAdapter的类,并且重写里面的很多方法,例如

 

class MyAdapter extends BaseAdapter
    {
        private Context context;
        public MyAdapter(Context context)
        {
            this.context = context;
        }
        @Override
        public int getCount() {
            // How many items are in the data set represented by this Adapter.(在此适配器中所代表的数据集中的条目数)
            return 0;
        }

        @Override
        public Object getItem(int position) {
            // Get the data item associated with the specified position in the data set.(获取数据集中与指定索引对应的数据项)
            return null;
        }

        @Override
        public long getItemId(int position) {
            // Get the row id associated with the specified position in the list.(取在列表中与指定索引对应的行id)
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            // Get a View that displays the data at the specified position in the data set.
            return null;
        }
        
    }
 

 

这里面没什么难度,但是这个getView方法必须好好处理,也是最麻烦的

第一种:没有任何处理,不建议这样写。如果数据量少看将就,但是如果列表项数据量很大的时候,会每次都重新创建View,设置资源,严重影响性能,所以从一开始就不要用这种方式

 

  @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View item = mInflater.inflate(R.layout.list_item, null);
            ImageView img = (ImageView)item.findViewById(R.id.img) 
            TextView title = (TextView)item.findViewById(R.id.title);
            TextView info = (TextView)item.findViewById(R.id.info);
            img.setImageResource(R.drawable.ic_launcher);
            title.setText("Hello");
            info.setText("world");
            
            return item;
        }
 第二种ListView优化:通过缓存convertView,这种利用缓存contentView的方式可以判断如果缓存中不存在View才创建View,如果已经存在可以利用缓存中的View,提升了性能

 

 

 public View getView(int position, View convertView, ViewGroup parent) {
            if(convertView == null)
            {
                convertView = mInflater.inflate(R.layout.list_item, null);
            }
            
            ImageView img = (ImageView)convertView.findViewById(R.id.img) 
            TextView title = (TextView)convertView.findViewById(R.id.title);
            TextView info = (TextView)ConvertView.findViewById(R.id.info);
            img.setImageResource(R.drawable.ic_launcher);
            title.setText("Hello");
            info.setText("world");
            
            return convertView;
        }
 

 

第三种ListView优化:通过convertView+ViewHolder来实现,ViewHolder就是一个静态类,使用 ViewHolder 的关键好处是缓存了显示数据的视图(View),加快了 UI 的响应速度。

当我们判断 convertView == null  的时候,如果为空,就会根据设计好的List的Item布局(XML),来为 convertView赋值,并生成一个viewHolder来绑定converView里面的各个View控件(XML布局里面的那些控件)。再用 convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。(看下面代码中)

如果convertView不为空的时候,就会直接用convertView的getTag(),来获得一个ViewHolder。

 

 

 //在外面先定义,ViewHolder静态类
    static class ViewHolder
    {
        public ImageView img;
        public TextView title;
        public TextView info;
    }
//然后重写getView
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if(convertView == null)
            {
                holder = new ViewHolder();
                convertView = mInflater.inflate(R.layout.list_item, null);
                holder.img = (ImageView)item.findViewById(R.id.img) 
                holder.title = (TextView)item.findViewById(R.id.title);
                holder.info = (TextView)item.findViewById(R.id.info);
                convertView.setTag(holder);
            }else
            {
                holder = (ViewHolder)convertView.getTag();
                holder.img.setImageResource(R.drawable.ic_launcher);
                holder.title.setText("Hello");
                holder.info.setText("World");
            }
            
            return convertView;
        }
 

 

到这里,可能会有人问ViewHolder静态类结合缓存convertView与直接使用convertView有什么区别吗,是否重复了

在这里,官方给出了解释

提升Adapter的两种方法

To work efficiently the adapter implemented here uses two techniques:
-It reuses the convertView passed to getView() to avoid inflating View when it is not necessary

(译:重用缓存convertView传递给getView()方法来避免填充不必要的视图)
-It uses the ViewHolder pattern to avoid calling findViewById() when it is not necessary

(译:使用ViewHolder模式来避免没有必要的调用findViewById():因为太多的findViewById也会影响性能)
ViewHolder类的作用
-The ViewHolder pattern consists in storing a data structure in the tag of the view
returned by getView().This data structures contains references to the views we want to bind data to,
thus avoiding calling to findViewById() every time getView() is invoked

(译:ViewHolder模式通过getView()方法返回的视图的标签(Tag)中存储一个数据结构,这个数据结构包含了指向我们

要绑定数据的视图的引用,从而避免每次调用getView()的时候调用findViewById())

//////////////////////////////////////////*****以上为转载内容*******////////////////////////////////

 

下面根据自己的体会和经验自己写一个简单的 Demo来帮助自己学习

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=".MainActivity" >

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true" >
    </ListView>

</RelativeLayout>

 

list_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"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/img"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_alignParentLeft="true" />

  
    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/img"
        android:textColor="@android:color/black"
        android:textSize="15sp" />

    <TextView
        android:id="@+id/info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/title"
        android:layout_below="@id/title"
        android:textColor="@android:color/black"
        android:textSize="13sp" />

    <TextView
        android:id="@+id/tvTime"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:textSize="22sp" />

</RelativeLayout>

 

   MainActivity.java文件

package com.example.listview_baseadapterdemo;

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



import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class MainActivity extends Activity {

	private ListView listView = null;
	private List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		setData();
		
		listView=(ListView) findViewById(R.id.listView);
		List_Adapater adapter = new List_Adapater(this, list);
		listView.setAdapter(adapter);

		
		
		
		
		listView.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				// 显示选中的那一项的在数组中的下标
				Toast.makeText(MainActivity.this, "" + position,
						Toast.LENGTH_SHORT).show();
			}
		});
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	private void setData() {

		Map<String, Object> map = null;
		int[] imgrs={ R.drawable.build,R.drawable.cloudly, R.drawable.down,
				     R.drawable.ic_launcher,R.drawable.local, R.drawable.love,
				     R.drawable.music_icon_default};
		
	for(int i=0;i<imgrs.length;i++){
		
		map=new HashMap<String, Object>();
		
		map.put("title", "G"+i);
		map.put("info", "google "+i);
		map.put("time", "time "+i);
		map.put("img", imgrs[i]);
		list.add(map);
	}

		
		
		
		
	}

}

 

   List_Adapater.java文件

 

package com.example.listview_baseadapterdemo;

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

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class List_Adapater extends BaseAdapter {

	private Context context;
	private List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

	public List_Adapater(Context context, List<Map<String, Object>> list) {
		super();
		this.context = context;
		this.list = list;
		
	}

	@Override
	public int getCount() {

		return list.size();
	}

	@Override
	public Object getItem(int position) {

		return position;
	}

	@Override
	public long getItemId(int position) {

		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {

		ViewHolder viewHolder = null;
		if (convertView == null) {
			viewHolder = new ViewHolder();

			convertView = LayoutInflater.from(context).inflate(
					R.layout.list_item, null);

			viewHolder.imageView = (ImageView) convertView
					.findViewById(R.id.img);
			viewHolder.tvTitle = (TextView) convertView
					.findViewById(R.id.title);
			viewHolder.tvArist = (TextView) convertView.findViewById(R.id.info);
			viewHolder.tvTime = (TextView) convertView
					.findViewById(R.id.tvTime);
			convertView.setTag(viewHolder);
		}else {
			viewHolder=(ViewHolder) convertView.getTag();
		}
		
		Map<String, Object> item=list.get(position);
		viewHolder.imageView.setImageResource((Integer) item.get("img"));
		viewHolder.tvTitle.setText((String)item.get("title"));
		viewHolder.tvArist.setText((String)item.get("info"));
		viewHolder.tvTime.setText((String)item.get("time"));

		return convertView;
	}

	public class ViewHolder {
		public ImageView imageView; // 专辑图片
		public TextView tvTitle; // 音乐图标
		public TextView tvTime;// 音乐时长
		public TextView tvArist; // 音乐艺术家
	}

}

 

运行效果:




 

 

 

  • 大小: 106.7 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics