Android進階:網路與資料儲存—步驟1:Android網路與通訊(第3小節:ListView上)
阿新 • • 發佈:2018-12-13
內容概要:
一、課程介紹
二、ListView的準備工作
- ListView簡介
- ListView的實現步驟
三、ListView簡單應用
- Adapter的資料繫結
- 最簡單ListView效果演示
- 獲取系統已安裝應用列表
- 優化效能
一、課程介紹
什麼是ListView?
- 列表檢視
應用場景:
- 通訊錄,簡訊列表
- 聊天聯絡人,聊天介面,好友動態
- 設定介面,各種列表介面
- 資料夾列表,應用列表
- O2O美食外賣等商家列表,評論列表
二、ListView的準備工作
2-1.ListView簡介
1.adapter建立及原理
(介面卡)它主要用來將資料繫結到相應元件上
二、.ListView的實現步驟
- 在Layout中建立ListView
- 建每一個行的item的樣式
- 建立每一行的資料
- 用adapter將資料填充到每一行的檢視
三、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快取拿就好。