内容概要:
一、课程介绍
二、ListView的准备工作
- ListView简介
- ListView的实现步骤
三、ListView简单应用
- Adapter的数据绑定
- 最简单ListView效果演示
- 获取系统已安装应用列表
- 优化性能
一、课程介绍
什么是ListView?
- 列表视图
应用场景:
- 通讯录,短信列表
- 聊天联系人,聊天界面,好友动态
- 设置界面,各种列表界面
- 文件夹列表,应用列表
- O2O美食外卖等商家列表,评论列表
二、ListView的准备工作
2-1.ListView简介
1.adapter创建及原理
(适配器)它主要用来将数据绑定到相应组件上
二、.ListView的实现步骤
- 在Layout中创建ListView
- 建每一个行的item的样式
- 创建每一行的数据
- 用adapter将数据填充到每一行的视图
mAdapter.notifyDataSetChanged(); 要在主线程进行!!!!
三、ListView简单应用
代码演示:
1、在Layout中创建ListView
<ListView
android:id="@+id/app_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
2、新建一个Layout创建每一个行的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="match_parent">
<ImageView
android:id="@+id/app_icom_image_view"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@mipmap/ic_launcher"/>
<TextView
android:id="@+id/app_name_image_view"
android:text="@string/app_name"
android:layout_width="match_parent"
android:layout_height="60dp"
android:textSize="20sp"
android:gravity="center_vertical"
android:paddingLeft="6dp"/>
</LinearLayout>
3、创建每一行的数据
List<String> appNames = new ArrayList<>();
appNames.add("QQ");
appNames.add("微信");
appNames.add("慕课网");
4、用adapter将数据填充到每一行的视图
BaseAdapter基础的Adapter
//把数据和视图适配的一个类
public class appListAdapter extends BaseAdapter {
//这是我们要填充的数据
List<String> mAppNames;
//构造函数初始化数据,将数据传进来
public appListAdapter(List<String> appNames) {
mAppNames = appNames;
}
@Override
public int getCount() {
//有多少条数据
return mAppNames.size();
}
@Override
public Object getItem(int position) {
//返回当前position的数据
return mAppNames.get(position);
}
@Override
public long getItemId(int position) {
//返回当前position的数据的id
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//1.处理View --data适配的过程(填充数据)三个参数(id,item视图,父组件)
//LayoutInflater(布局服务)是用来找res/layout/下的xml布局文件,并且实例化
LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//2.拿到item布局
convertView = layoutInflater.inflate(R.layout.item_app_list, null);
//3.拿到item布局的ImageView和TextView
TextView appNameTextView = convertView.findViewById(R.id.app_name_text_view);
ImageView appIconImageView = convertView.findViewById(R.id.app_icom_image_view);
//4.绑定数据
appNameTextView.setText(mAppNames.get(position));
return convertView;//返回视图
}
}
在初始化时setAdapter将ListView和数据item进行绑定
//将ListView设置item的数据
appListView.setAdapter(new appListAdapter(appNames));
效果演示:
4、实现获取系统已安装应用列表
1、获取系统应用的信息的方法
/**
* 获取所有的应用的信息的方法
* @return
*/
private List<ResolveInfo> getAppInfos(){
Intent intent=new Intent(Intent.ACTION_MAIN,null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
return getPackageManager().queryIntentActivities(intent,0);
}
2、适配器
//把数据和视图适配的一个类
public class appListAdapter extends BaseAdapter {
//这是我们要填充的数据
List<ResolveInfo> mAppInfos;
//构造函数初始化数据,将数据传进来
public appListAdapter(List<ResolveInfo> appNames) {
mAppInfos = appNames;
}
....这三个方法和上面一样
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//1.处理View --data适配的过程(填充数据)三个参数(id,item视图,父组件)
//LayoutInflater(布局服务)是用来找res/layout/下的xml布局文件,并且实例化
LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//2.拿到item布局
convertView = layoutInflater.inflate(R.layout.item_app_list, null);
//3.拿到item布局的ImageView和TextView
TextView appNameTextView = convertView.findViewById(R.id.app_name_text_view);
ImageView appIconImageView =
convertView.findViewById(R.id.app_icom_image_view);
//4.绑定系统应用的数据
appNameTextView.setText(mAppInfos.get(position).activityInfo.loadLabel(getPackageManager()));
appIconImageView.setImageDrawable(mAppInfos.get(position).activityInfo.loadIcon(getPackageManager()));
return convertView;//返回视图
}
}
3、为item添加点击效果
方法1:在getView方法中为
- 整个item添加监听事件
- ImageView添加监听事件将convertView修改成 appIconImageView即可(点击图片才跳转)
- TextView添加监听(同上)
//item布局的点击事件
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//拿出包名
String packageName=mAppInfos.get(position).activityInfo.packageName;
//应用本身的名字
String className=mAppInfos.get(position).activityInfo.name;
//用包名和应用的名称构造一个组件
ComponentName componentName=new ComponentName(packageName,className);
final Intent intent = new Intent();
intent.setComponent(componentName);
startActivity(intent);
}
});
方法2:直接在初始化时添加监听给ListView直接添加OnItemClickListener
final List<ResolveInfo> appInfos = getAppInfos();
appListView.setAdapter(new appListAdapter(appInfos));
appListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//拿出包名
String packageName=appInfos.get(position).activityInfo.packageName;
//应用本身的名字
String className=appInfos.get(position).activityInfo.name;
//构造一个组件
ComponentName componentName=new ComponentName(packageName,className);
final Intent intent = new Intent();
intent.setComponent(componentName);
startActivity(intent);
}
});
4、给ListView头部添加一个图片,图片随着列表一起滑动
//得到专们解析布局的layoutInflater
LayoutInflater layoutInflater= (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View headerView=layoutInflater.inflate(R.layout.header_list,null);
//给ListView头部添加一张随之滑动的图片(布局)
appListView.addHeaderView(headerView);
图片固定不动:
直接在ListView所在的布局添加一个图片就可以了。
4、优化性能
getView就是当前每一条item,所以滑动的时候一直在执行执行很多次,多了就会卡顿,出来一个就执行一次
每一次都要执行getView的操作重新拿到布局,重新找到控件id....很耗内存
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
//1.处理View --data适配的过程(填充数据)三个参数(id,item视图,父组件)
//LayoutInflater(布局服务)是用来找res/layout/下的xml布局文件,并且实例化
LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//2.拿到item布局
convertView = layoutInflater.inflate(R.layout.item_app_list, null);
//3.拿到item布局的ImageView和TextView
TextView appNameTextView = convertView.findViewById(R.id.app_name_text_view);
ImageView appIconImageView = convertView.findViewById(R.id.app_icom_image_view);
//4.绑定数据
......
解决方法:使用ViewHolder进行缓存
首先,新建一个ViewHolder类
//建立一个ViewHolder来缓存,让每次getView不用执行这么多重复操作
public class ViewHolder{
public TextView appNameTextView;
public ImageView appIconImageView;
}
在getView方法中
ViewHolder viewHolder=new ViewHolder();
if(convertView==null){//如果item为空
//1.处理View --data适配的过程(填充数据)三个参数(id,item视图,父组件)
//LayoutInflater(布局服务)是用来找res/layout/下的xml布局文件,并且实例化
LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//2.拿到item布局
convertView = layoutInflater.inflate(R.layout.item_app_list, null);
//3.拿到item布局的ImageView和TextView
//将这两个控件赋值给viewHolder,相当于它保存了两个视图
viewHolder.appNameTextView = convertView.findViewById(R.id.app_name_text_view);
viewHolder.appIconImageView = convertView.findViewById(R.id.app_icom_image_view);
convertView.setTag(viewHolder);//这个view视图保存起来给它个标签
}
else{
//如果不为空直接把上次存的viewHolder取出来:
// 它里面保存的appNameTextView、和appIconImageView
viewHolder=(ViewHolder) convertView.getTag();
}
//4.通过viewHolder绑定数据
viewHolder.appNameTextView.setText(mAppInfos.get(position).activityInfo.loadLabel(getPackageManager()));
viewHolder.appIconImageView.setImageDrawable(mAppInfos.get(position).activityInfo.loadIcon(getPackageManager()));
这样它每次就省掉了上面几步操作,直接出viewHolder缓存拿就好。