【小王的安卓之路】ListView的优化使用以及RecycleBin的原理

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,在这个类中,有几个变量值得我们注意

  1. private View[] mActiveView:这个数组记录的当前处于屏幕上的view,可以被直接复用
  2. private ArrayList[] mScrapView:所有废弃的view(已经被划过)
  3. private ArrayList[] mCurrentScrap:当前被废弃的view

同样的,还有几个重要的方法:

  1. setViewTypeCount():为listview中的每种item设置RecycleBin机制
  2. fillActiveViews():将正在屏幕上显示的item存储到mActivityView这个数组中,及初始化或者更新这个数组
  3. getActiveView():获取正在屏幕上显示的item.值得注意的一点是,当我们获取了这个view之后,存储这个view的数组会将对应下标的位置的元素置为空,即在此调用这个方法获取想用下标的原色的时候会返回null。
  4. addScrapView():将已经废弃的view存入到mScrapView数组中
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值