ListView的优化使用
一.ListView样式
我们平时看到的评论类的消息类的一条一条的数据,一般来说都是ListView的样式(虽然可能大部分都是RecycleView),但他们实现的样式基本类似。本文以实现获取所有系统应用的名称和图标为例。
二.ListView的优化使用方法
(普通方法就不写了)
2.1在布局文件中:
直接写入一个ListView,定义它的id.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ApplistActivity">
<ListView
android:id="@+id/viewlist"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</LinearLayout>
这里我们就有了这样的一个样式:
然后我们写一个ListView中每一个Item的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ImageView
android:id="@+id/appImage"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@mipmap/ic_launcher"/>
<TextView
android:id="@+id/appName"
android:layout_width="match_parent"
android:layout_height="60dp"
android:gravity="center_vertical"
android:paddingLeft="6dp"
android:textSize="20dp"
android:text="@string/app_name"/>
</LinearLayout>
我们为每一个Item设置了一张图片和一段文字,样式是这样的:
这个就作为了Item的样式。
然后我们开始给ListView写一个适配器,用来把你的资源和ListView的Item的布局绑定起来。
package com.example.handlerest;
public class AppListAdapter extends BaseAdapter {
List<ResolveInfo> myAppInfos;
public AppListAdapter(List<ResolveInfo> appNames) {
this.myAppInfos = appNames;
}
@Override
public int getCount() {
//获取数据总数
return myAppInfos.size();
}
@Override
public Object getItem(int position) {
//获取当前position这条item
return myAppInfos.get(position);
}
@Override
public long getItemId(int position) {
//返回当前item的id
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
//填充数据的过程
ViewHolder viewHolder = new ViewHolder();
/*如果Item不存在,则通过LayoutInflater去获取Item的布局*/
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.item_app_list_view, null);
viewHolder.mappImage = convertView.findViewById(R.id.appImage);
viewHolder.mappNames = convertView.findViewById(R.id.appName);
convertView.setTag(viewHolder);//保存ViewHolder
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
/**
* 通过viewholder去刷新控件
*/
viewHolder.mappNames.setText(myAppInfos.get(position).activityInfo.loadLabel(getPackageManager()));
viewHolder.mappImage.setImageDrawable(myAppInfos.get(position).activityInfo.loadIcon(getPackageManager()));
/*Item的点击事件*/
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String packageName = myAppInfos.get(position).activityInfo.packageName;
String className = myAppInfos.get(position).activityInfo.name;
ComponentName componentName = new ComponentName(packageName, className);
final Intent intent = new Intent();
intent.setComponent(componentName);
startActivity(intent);
}
});
return convertView;
}
public class ViewHolder {
public ImageView mappImage;
public TextView mappNames;
}
}
}
然后再Activity文件中,去加载ListView.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_applist);
ListView appListView = findViewById(R.id.viewlist);
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
//设置顶部图片
View headView = inflater.inflate(R.layout.headview, null);
appListView.addHeaderView(headView);
appListView.setAdapter(new AppListAdapter(getAppInfos()));
}
// 获取所有的用户信息
private List<ResolveInfo> getAppInfos() {
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
return getPackageManager().queryIntentActivities(intent, 0);
}
如果要实现在ListView的最上边,添加一个header,我们可以设置ListView的HeadView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="60dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="@drawable/digleet"/>
</LinearLayout>
最后实现的效果如下:
三.RecycleBin的原理
我们知道,ListView是继承自AbsListView的。在AbsListView中,有一个内部类就是RecycleBin,在这个类中,有几个变量值得我们注意
- private View[] mActiveView:这个数组记录的当前处于屏幕上的view,可以被直接复用
- private ArrayList[] mScrapView:所有废弃的view(已经被划过)
- private ArrayList[] mCurrentScrap:当前被废弃的view
同样的,还有几个重要的方法:
- setViewTypeCount():为listview中的每种item设置RecycleBin机制
- fillActiveViews():将正在屏幕上显示的item存储到mActivityView这个数组中,及初始化或者更新这个数组
- getActiveView():获取正在屏幕上显示的item.值得注意的一点是,当我们获取了这个view之后,存储这个view的数组会将对应下标的位置的元素置为空,即在此调用这个方法获取想用下标的原色的时候会返回null。
- addScrapView():将已经废弃的view存入到mScrapView数组中