【小王的安卓之路】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的佈局綁定起來。

 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不存在*/
            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.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的最上邊,加載一張圖片,我們可以設置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數組中
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章