Android 自定義介面卡
1. BaseAdapter:是所有介面卡類的父類,可以對列表項進行最大限度的定製
1.1 自定義介面卡中的方法
getCount
getView
getItem
getItemId
1.2 LayoutInflater(佈局解析器)
--LayoutInflater有三種獲得方式,資料中有詳細介紹
用來把layout佈局檔案解析成一個View物件,不可以new,需要使用系統服務獲得
inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
案例一:ListView的使用及優化
2. ListView優化
2.1 使用ConvertView重用元件
即拖動時被遮住、看不見的控制元件,重用它,而非每次建立一個新的物件
2.2 使用內部類ViewHolder+ConvertView.setTag()儲存控制元件,而不用每次查詢
ViewHolder(檢視的持有者)
2.3 使用分頁查詢(PullToRefresh)
2.3.2 使用AsyncTask(非同步任務)載入資料,最少要重寫以下這兩個方法
doInBackground
後臺執行
onPostExecute
在doInBackground方法執行結束之後在執行,並且執行在UI執行緒當中 可以對UI空間進行設定
關鍵程式碼:
myListViewAdapter.notifyDataSetChanged();// 通知介面卡資料已改變
ptrlv_main_1.onRefreshComplete();// 通知控制元件資料已經載入完畢
2.4 事件監聽的優化
假設Item中有三個按鈕,要為三個按鈕定義事件,如果是下面這樣
btn1.setOnclickListener(new View.onClickListener(){
public void onClick(View view){
//...
}
});
btn2.setOnclickListener(new View.onClickListener(){
public void onClick(View view){
//...
}
});
btn3.setOnclickListener(new View.onClickListener(){
public void onClick(View view){
//...
}
});
如果每屏顯示10個Item,那一共建立了30個listener物件在記憶體中。
如果,你是在Adapter建立時,只建立一個Listener,並將其定義成全域性屬性,
然後通過按鈕的ID來進行判斷是哪個事件應該觸發,
class MyAdapter extends BaseAdapter{
View.onClickListener myListener = new View.onClickListener(){
public void onClick(View view){
if(view.getId() == R.id.btn1){
//...
}else if(view.getId() == R.id.btn2){
//...
}else if(view.getId() == R.id.btn3){
//...
}
}
});
}
//註冊監聽器
btn1.setOnclickListener(myListener);
btn2.setOnclickListener(myListener);
btn3.setOnclickListener(myListener);
2.5 另外,真實開發中,圖片肯定是通過網路下載,也需要通過執行緒非同步下載進行優化等等,但由於還涉及到android網路程式設計,
這部分的內容會在之後的課程中介紹
3. 第三方控制元件:上拉載入、下拉重新整理控制元件
3.1 匯入第三方外掛庫
Android-PullToRefresh-master.zip
3.2 在佈局檔案中使用第三方外掛
com.handmark.pulltorefresh.library.PullToRefreshListView
3.3 自定義介面卡(BaseAdapter)提供資料
3.4 非同步任務查詢資料(AsyncTask)
3.4.1 AsyncTask定義了三種泛型型別 Params,Progress和Result。
Params 啟動任務執行的輸入引數,比如HTTP請求的URL。
Progress 後臺任務執行的百分比。
Result 後臺執行任務最終返回的結果,比如String
3.4.2 非同步載入資料最少要重寫以下這兩個方法
doInBackground(Params…) 後臺執行,比較耗時的操作都可以放在這裡
onPostExecute(Result) 相當於Handler 處理UI的方式,在這裡面可以使用在doInBackground 得到的結果處理操作UI
--注:此方法中再通知介面卡和控制元件
myBaseAdapter.notifyDataSetChanged();// 通知介面卡資料已改變
plv_main_plv1.onRefreshComplete();// 通知控制元件資料已經載入完畢
3.5 給PullToRefreshListView設定相關屬性
plv_main_1.setMode(Mode.BOTH);// 設定重新整理模式
Mode.BOTH:同時支援上拉下拉
Mode.PULL_FROM_START:只支援下拉Pulling Down
Mode.PULL_FROM_END:只支援上拉Pulling Up
plv_main_1.getLoadingLayoutProxy().setPullLabel("上拉重新整理...");// 剛下拉時,顯示的提
plv_main_1.getLoadingLayoutProxy().setRefreshingLabel("正在載入...");// 重新整理時
plv_main_1.getLoadingLayoutProxy().setReleaseLabel("放開重新整理...");// 下來達到一定距離時,顯示的提示
3.6 給PullToRefreshListView設定介面卡
3.7 給PullToRefreshListView設定監聽器
監聽器有二種:第一種上拉和下拉重新整理的效果是一樣的,要想實現上拉和下拉重新整理效果不一樣就要使用第二種
setOnRefreshListener/PullToRefreshBase.OnRefreshListener
setOnRefreshListener2/PullToRefreshBase.OnRefreshListener2
核心:
1、listview控制元件、項資源、自定義介面卡準備好
2、向服務端拿資料
3、初始化自定介面卡(獲取檢視解析器、得到項資源的view控制元件、獲取所有的子控制元件,給子控制元件賦值、返回view)
4、繫結介面卡
package com.example.t212_a08; import android.content.Context; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import java.util.List; public class MainActivity extends AppCompatActivity { private List<Book> data; private ListView lv_main_lv1; private MyBaseAdapter myBaseAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); lv_main_lv1 = this.findViewById(R.id.lv_main_lv1); this.data = new BookDao().list(); myBaseAdapter = new MyBaseAdapter((LayoutInflater) getSystemService(this.LAYOUT_INFLATER_SERVICE)); lv_main_lv1.setAdapter(myBaseAdapter); } //定義一個自定義介面卡 public class MyBaseAdapter extends BaseAdapter{ //用來儲存控制元件的內部類 public class ViewHolder{ //定義屬性 ImageView iv_listviewitem_image; TextView tv_listviewitme_title; TextView tv_listviewitme_author; TextView tv_listviewitme_price; TextView tv_listviewitme_publish; TextView tv_listviewitme_remark; ImageButton bt_listviewitme_btn1; ImageButton bt_listviewitme_btn2; } //定義一個解析器 private LayoutInflater inflater; //定義一個有參 public MyBaseAdapter(LayoutInflater inflater) { this.inflater = inflater; } /** * 資料的長度 * @return */ @Override public int getCount() { return data.size(); } /** * 獲取第幾個項 * @param i * @return */ @Override public Object getItem(int i) { return data.get(i); } /** * 返回下標 * @param position * @return */ @Override public long getItemId(int position) { return position; } /** * * @param position 迴圈到的下標 * @param convertView 被遮擋的檢視 * @param parent * @return */ @Override public View getView(int position, View convertView, ViewGroup parent) { //將資原始檔轉為 View檢視 View v = convertView; ViewHolder viewHolder; if(v==null){//當沒有檢視被遮擋 (相當於當前建立的檢視還不夠佔滿螢幕) Log.i("test","position"+position); v = inflater.inflate(R.layout.listview_item,null); //例項化一個控制元件 viewHolder = new ViewHolder(); //獲取控制元件 viewHolder.iv_listviewitem_image = v.findViewById(R.id.iv_listviewitem_image); viewHolder.tv_listviewitme_title = v.findViewById(R.id.tv_listviewitme_title); viewHolder.tv_listviewitme_author = v.findViewById(R.id.tv_listviewitme_author); viewHolder.tv_listviewitme_price = v.findViewById(R.id.tv_listviewitme_price); viewHolder.tv_listviewitme_publish = v.findViewById(R.id.tv_listviewitme_publish); viewHolder.tv_listviewitme_remark = v.findViewById(R.id.tv_listviewitme_remark); //給視圖裡放控制元件 v.setTag(viewHolder); }else {//噹噹前建立的檢視足夠用了時 為了優化只需要把新的檢視把原來的檢視覆蓋 v = convertView; } //往控制元件裡賦值 //根據下標獲取物件 ViewHolder vh = (ViewHolder) v.getTag(); Book book = data.get(position); vh.iv_listviewitem_image.setImageResource(book.getImage()); vh.tv_listviewitme_title.setText(book.getTitle()); vh.tv_listviewitme_author.setText(book.getAuthor()); vh.tv_listviewitme_price.setText(book.getPrice()+""); vh.tv_listviewitme_publish.setText(book.getPublish()); vh.tv_listviewitme_remark.setText(book.getRemark()); return v; } } }