ListView的优化和自定义适配器继承于BaseAdapter

时间:2022-10-06 16:05:54

                         ListView的优化和万能适配器继承于BaseAdapter

         在android开发中Listview是一个很重要的组件,它以列表的形式根据数据的长自适应展示具体内容,用户可以*的定义listview每一列的布局,但当listview有大量的数据需要加载的时候,会占据大量内存,影响性能,这时候就需要按需填充并重新使用view来减少对象的创建。

     一、复用convertView
      首先讲下ListView的原理:ListView中的每一个Item显示都需要Adapter调用一次getView的方法,这个方法会传入一个convertView的参数,返回的View就是这个Item显示的View。如果当Item的数量足够大,再为每一个Item都创建一个View对象,必将占用很多内存,创建View对象(mInflater.inflate(R.layout.lv_item, null);从xml中生成View,这是属于IO操作)也是耗时操作,所以必将影响性能。Android提供了一个叫做Recycler(反复循环器)的构件,就是当ListView的Item从上方滚出屏幕视角之外,对应Item的View会被缓存到Recycler中,相应的会从下方生成一个Item,而此时调用的getView中的convertView参数就是滚出屏幕的Item的View,所以说如果能重用这个convertView,就会大大改善性能

     二,ViewHolder类

     避免了就是每次在getVIew的时候,都需要重新的findViewById,重新找到控件,然后进行控件的赋值以及事件相应设置。这样其实在做重复的事情)

     三 自定义适配器BaseAdapter

      抽取BaseAdapter类里面的方法写一个自定义适配器,因为一个项目中会有多次使用到适配器,其实每次使用,我们主要是写getView方法和传入数据,所以把其他的方法抽取出来写到一个自定义类里面,供多次使用,看看我的代码就知道了.

     看看我写的自定义适配器

    ListView的优化和自定义适配器继承于BaseAdapter

   MyBaseAdapter.java

package com.gaomin.myBaseAdapter;

import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

import java.util.List;

/**
* Created by gaomin on 2016/3/21.
*/
public abstract class MyBaseAdapter<T> extends BaseAdapter{
public List<T> T;

public MyBaseAdapter(List<T> t){
T=t;
}
@Override
public int getCount() {
return T.size();
}

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

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

@Override
public abstract View getView(int position, View convertView, ViewGroup parent);
}

等会在程序中会使用的,先把布局文件贴出来吧

activity_main.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">
<ListView
android:id="@+id/mListView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>

每一项的布局

listview_item.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:orientation="horizontal">

<ImageView
android:id="@+id/singerImageView"
android:layout_width="100dp"
android:layout_height="50dp" />

<TextView
android:id="@+id/songInfoTextView"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:textColor="#DD017F"
android:textSize="10dp" />

<TextView
android:id="@+id/singerTextView"
android:layout_width="70dp"
android:layout_height="wrap_content"
android:textColor="#DD017F"
android:textSize="13dp" />
<!--
ListView的item中加入Button后 导致ListView对OnItemClick事件无法响应
原因是因为Button的事件响应优先级高于List Item,所以屏蔽了ListItem的单击事件
android:focusableInTouchMode="false"
android:clickable="false"
-->

<Button
android:id="@+id/deleteSongBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:focusable="false"
android:text="删除"
android:textColor="#025730" />
<!--@android:color/transparent让按钮变透明-->
<Button
android:id="@+id/downLoadSongBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:focusable="false"
android:text="下载"
android:textColor="#025730" />
</LinearLayout>
 

   最后就是将要实现程序的主要java代码了

package com.gaomin.listViewDemo;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.gaomin.myBaseAdapter.MyBaseAdapter;

import java.util.ArrayList;
import java.util.HashMap;

public class MainActivity extends Activity {
private SongAdapter songAdapter;
private ListView mListView;
private ArrayList songArrayList;
private HashMap songMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView =(ListView)findViewById(R.id.mListView);

songArrayList = new ArrayList();
songMap = new HashMap();
songMap.put("image",R.mipmap.lyf);
songMap.put("singer","林心如");
songMap.put("songInfo","一万个舍不得");
songArrayList.add(songMap);

songMap = new HashMap();
songMap.put("image",R.mipmap.lyf);
songMap.put("singer","宋慧乔");
songMap.put("songInfo","太阳的后裔");
songArrayList.add(songMap);

songMap = new HashMap();
songMap.put("image",R.mipmap.lyf);
songMap.put("singer","庄心妍");
songMap.put("songInfo","一直还想着她");
songArrayList.add(songMap);

songMap = new HashMap();
songMap.put("image",R.mipmap.lyf);
songMap.put("singer","林心如");
songMap.put("songInfo","一万个舍不得");
songArrayList.add(songMap);

songMap = new HashMap();
songMap.put("image",R.mipmap.lyf);
songMap.put("singer","宋慧乔");
songMap.put("songInfo","太阳的后裔");
songArrayList.add(songMap);

songMap = new HashMap();
songMap.put("image",R.mipmap.lyf);
songMap.put("singer","庄心妍");
songMap.put("songInfo","一直还想着她");
songArrayList.add(songMap);

songMap = new HashMap();
songMap.put("image",R.mipmap.lyf);
songMap.put("singer","林心如");
songMap.put("songInfo","一万个舍不得");
songArrayList.add(songMap);

songMap = new HashMap();
songMap.put("image",R.mipmap.lyf);
songMap.put("singer","宋慧乔");
songMap.put("songInfo","太阳的后裔");
songArrayList.add(songMap);

songMap = new HashMap();
songMap.put("image",R.mipmap.lyf);
songMap.put("singer","庄心妍");
songMap.put("songInfo","一直还想着她");
songArrayList.add(songMap);

songMap = new HashMap();
songMap.put("image",R.mipmap.lyf);
songMap.put("singer","林心如");
songMap.put("songInfo","一万个舍不得");
songArrayList.add(songMap);

songMap = new HashMap();
songMap.put("image",R.mipmap.lyf);
songMap.put("singer","宋慧乔");
songMap.put("songInfo","太阳的后裔");
songArrayList.add(songMap);

songMap = new HashMap();
songMap.put("image",R.mipmap.lyf);
songMap.put("singer","庄心妍");
songMap.put("songInfo","一直还想着她");
songArrayList.add(songMap);

songMap = new HashMap();
songMap.put("image",R.mipmap.lyf);
songMap.put("singer","林心如");
songMap.put("songInfo","一万个舍不得");
songArrayList.add(songMap);

songMap = new HashMap();
songMap.put("image",R.mipmap.lyf);
songMap.put("singer","宋慧乔");
songMap.put("songInfo","太阳的后裔");
songArrayList.add(songMap);

songMap = new HashMap();
songMap.put("image",R.mipmap.lyf);
songMap.put("singer","庄心妍");
songMap.put("songInfo","一直还想着她");
songArrayList.add(songMap);



if(songAdapter==null){
songAdapter = new SongAdapter(this,songArrayList);
}else {
//刷新适配器,不用每次都new SongAdapter(this,songArrayList)
songAdapter.notifyDataSetChanged();
}
mListView.setAdapter(songAdapter);

}
class SongAdapter extends MyBaseAdapter<ArrayList>{
private Context context;
SongAdapter(Context c,ArrayList arrayList){
super(arrayList);
context=c;
}
//重用了convertView,很大程度上的减少了内存的消耗。通过判断convertView是否为null,
// 是的话就需要产生一个视图出来,然后给这个视图数据,最后将这个视图返回给底层,呈献给用户。
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if(convertView==null){
LayoutInflater inflater = LayoutInflater.from(context);
convertView =inflater.inflate(R.layout.listview_item,null);

viewHolder = new ViewHolder();
viewHolder.singerImageView =(ImageView)convertView.findViewById(R.id.singerImageView);
viewHolder.songInfoTextView =(TextView)convertView.findViewById(R.id.songInfoTextView);
viewHolder.singerTextView =(TextView)convertView.findViewById(R.id.singerTextView);
viewHolder.deleteSongBtn =(Button)convertView.findViewById(R.id.deleteSongBtn);
viewHolder.downLoadSongBtn=(Button)convertView.findViewById(R.id.downLoadSongBtn);

convertView.setTag(viewHolder);
viewHolder.deleteSongBtn.setTag(position);
viewHolder.downLoadSongBtn.setTag(position);
}else {
viewHolder =(ViewHolder)convertView.getTag();
}
viewHolder.singerImageView.setImageResource((Integer)
((HashMap)songArrayList.get(position)).get("image"));
viewHolder.singerTextView.setText((String)((HashMap)songArrayList.get(position)).get("singer"));
viewHolder.songInfoTextView.setText((String)((HashMap)songArrayList.get(position)).get("songInfo"));

viewHolder.deleteSongBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int dePosition = (Integer)v.getTag();
songArrayList.remove(dePosition);
songAdapter.notifyDataSetChanged();
}
});
viewHolder.downLoadSongBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int downLoadPosition =(Integer)v.getTag();
String singerStr =(String)((HashMap)songArrayList.get(downLoadPosition)).get("singer");
String songStr =(String)((HashMap)songArrayList.get(downLoadPosition)).get("songInfo");
String toastStr =singerStr+songStr;
Toast.makeText(getApplicationContext(),"你准备下载"+toastStr,Toast.LENGTH_SHORT).show();
}
});
return convertView;
}
}
//避免了就是每次在getVIew的时候,都需要重新的findViewById,
// 重新找到控件,然后进行控件的赋值以及事件相应设置。这样其实在做重复的事情)
class ViewHolder{
ImageView singerImageView;
TextView songInfoTextView;
TextView singerTextView;
Button deleteSongBtn;
Button downLoadSongBtn;
}
}

运行截图

ListView的优化和自定义适配器继承于BaseAdapter