編輯:關於Android編程
本篇介紹ListView控件,這是Android中比較重要也比較復雜的控件,這裡只談到使用ViewHolder機制優化即可。
ListView是Android系統中顯示列表的控件,每個ListView都可以包含很多個列表項。
概念不多說,直接來介紹使用方法。
ListView中比較復雜的是數據適配器,其作用是把復雜的數據(數組、鏈表、數據庫、集合等)填充在指定視圖界面,是連接數據源和視圖界面的橋梁。常見的Android原生的適配器有ArrayAdapter和SimpleAdapter。
使用步驟:新建適配器->添加數據源到適配器->視圖加載適配器
適用:用於綁定格式單一的數據;
數據源:可以使集合或數組。
public class MainActivity extends Activity { private ListView listView; // 1. 新建一個數據適配器 private ArrayAdapterarr_aAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView)findViewById(R.id.listView1); // 創建適配器對象時將數據加載到適配器裡 /**new ArrayAdapter (context, textViewResourceId) * context-- 上下文,一般為this * textViewResourceId-- 當前ListView加載的每一個列表項所對應的布局文件【這裡采用系統默認的一個布局android.R.layout.simple_list_item_1】 */ // 2. 添加數據源到適配器 String[] arr_data = {"fanff", "fan", "tencent", "QQ"};// 創建的數據源 arr_aAdapter = new ArrayAdapter (this, android.R.layout.simple_list_item_1, arr_data); // 3. 視圖(ListView)加載適配器 listView.setAdapter(arr_adAdapter); } }
適用:綁定格式復雜的數組;
數據源:只能是特定泛型的集合。
public class MainActivity extends Activity { private ListView listView; private SimpleAdapter sim_aAdapter; // 1. 新建一個數據適配器 private List
一般來講,簡單適配器的數據源是一個集合,所以一般寫一個方法來處理(例如getData())。
其中自定義的item.xml布局
這個玩法比較多,這裡先不介紹,直接見下面的。
(1). 監聽器是程序和用戶(或系統)交互的橋梁,這裡不多講了,畢竟用的多。ListView中的兩個常用監聽器:OnItemClickListener和OnScrollListener。
(2). OnItemClickListener可以處理視圖中單個條目的點擊事件;OnScrollListener監測滾動的變化,可以用於視圖在滾動中加載數據。
public class MainActivity extends Activity implements OnItemClickListener, OnScrollListener { private ListView listView; private ArrayAdapterarr_aAdapter; private SimpleAdapter sim_aAdapter; private List > dataList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); listView = (ListView) findViewById(R.id.listView1); /** * 1. 新建一個數據適配器 context: 上下文 data: 數據源(List> * data),一個Map所組成的List集合 * 每個Map都會對應ListView列表中的一行,Map是由鍵【必須包含所有在from中所指定的鍵】值對組成 from:Map中的鍵名 * resource:列表中的布局文件的ID to:綁定數據視圖中的ID,與from成對應關系 */ // 2. 適配器加載數據源 dataList = new ArrayList >(); sim_aAdapter = new SimpleAdapter(this, getData(), R.layout.item, new String[] { "pic0", "text0" }, new int[] { R.id.pic, R.id.text }); // 3. 視圖(ListView)加載適配器 listView.setAdapter(sim_aAdapter); // 監聽器 listView.setOnItemClickListener(this);// 單擊單個條目 listView.setOnScrollListener(this);// 視圖在滾動中加載數據 } private List > getData() { for (int i = 0; i < 20; i++) { Map map = new HashMap (); map.put("pic0", R.drawable.ic_launcher); map.put("text0", "fanff" + i); dataList.add(map); } return dataList; } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // TODO Auto-generated method stub } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { // TODO Auto-generated method stub switch (scrollState) { case SCROLL_STATE_FLING: Log.i("ScrollState", "用戶在手指離開屏幕之前,由於用力滑了一下,視圖仍依靠慣性在繼續滑行"); Map map = new HashMap (); map.put("pic0", R.drawable.ic_launcher); map.put("text0", "fresh"); dataList.add(map); sim_aAdapter.notifyDataSetChanged();// 通知UI進程刷新界面 break; case SCROLL_STATE_IDLE: Log.i("ScrollState", "視圖已經停止滑動"); break; case SCROLL_STATE_TOUCH_SCROLL: Log.i("ScrollState", "手指乜有離開屏幕,視圖正在滑動"); break; default: break; } } @Override public void onItemClick(AdapterView parent, View view, int position, long id) { // TODO Auto-generated method stub String text = listView.getItemAtPosition(position) + "";// 指定位置的內容 Toast.makeText(this, "positon=" + position + "text" + text, Toast.LENGTH_LONG).show(); } }
這裡著重來介紹一下BaseAdapter,各種方式的比較見代碼注釋。
源碼下載:https://github.com/herdyouth/ListView
MainActivity
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListitemBeanList = new ArrayList<>(); for (int i = 0; i < 20; i++){ itemBeanList.add(new ItemBean(R.mipmap.ic_launcher, "標題" + i, "內容" + i)); } // 數據源與適配器的綁定 ListView listView = (ListView) findViewById(R.id.lview); listView.setAdapter(new MyBaseAdapter(this, itemBeanList)); } }
BaseAdapter各種方式的對比,一步步優化的原因如代碼注釋
/** * 創建數據適配器 * Created by herd_youth on 2016/4/15. */ public class MyBaseAdapter extends BaseAdapter{ private ListmList; private LayoutInflater mInflater; // 通過構造器關聯數據源與數據適配器 public MyBaseAdapter(Context context, List list){ mList = list; // 使用當前要使用的界面對象context去初始化布局裝載器對象mInflater mInflater = LayoutInflater.from(context); } @Override public int getCount() { return mList.size(); } @Override public Object getItem(int position) { return mList.get(position); } // 返回指定索引對應的數據項 @Override public long getItemId(int position) { return position; } /* *//** * 返回每一項對應的內容 * 缺點:沒有利用到ListView的緩存機制 * 每次都會創建新的View,不管當前這個Item是否在屏幕上被調用過(即是否被緩存過) * @param position * @param convertView * @param parent * @return *//* @Override public View getView(int position, View convertView, ViewGroup parent) { // 將布局文件轉為View對象 View view = mInflater.inflate(R.layout.item, null); ImageView imageView = (ImageView) view.findViewById(R.id.iv_img); TextView title = (TextView) view.findViewById(R.id.tv_title); TextView content = (TextView) view.findViewById(R.id.tv_content); ItemBean bean = mList.get(position); imageView.setImageResource(bean.getItemImageResid()); title.setText(bean.getItemContent()); content.setText(bean.getItemContent()); return view; }*/ /** * 改善處:使用系統的convertView來較好的利用ListView的緩存機制,避免重復大量的創建convertView * 缺點:findViewById依然會浪費大量的時間去調用視圖樹 * @param position * @param convertView * @param parent * @return *//* @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null){// View未被實例化,即緩沖池中無緩存才創建View convertView = mInflater.inflate(R.layout.item, null); }else{ ImageView imageView = (ImageView) convertView.findViewById(R.id.iv_img); TextView title = (TextView) convertView.findViewById(R.id.tv_title); TextView content = (TextView) convertView.findViewById(R.id.tv_content); ItemBean bean = mList.get(position); imageView.setImageResource(bean.getItemImageResid()); title.setText(bean.getItemContent()); content.setText(bean.getItemContent()); } return convertView; }*/ /** * 既利用了ListView的緩存, * 更通過ViewHolder類來顯示數據的視圖的緩存,避免了多次通過findViewById尋找控件 * @param position * @param convertView * @param parent * @return */ @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if (convertView == null){// View未被實例化,即緩沖池中無緩存才創建View // 將控件id保存在viewHolder中 viewHolder = new ViewHolder(); viewHolder.imageView = (ImageView) convertView.findViewById(R.id.iv_img); viewHolder.title = (TextView) convertView.findViewById(R.id.tv_title); viewHolder.content = (TextView) convertView.findViewById(R.id.tv_content); // 通過setTag將ViewHolder與convertView綁定 convertView.setTag(viewHolder); } else{ // 通過ViewHolder對象找到對應控件 viewHolder = (ViewHolder) convertView.getTag(); ItemBean bean = mList.get(position); viewHolder.imageView.setImageResource(bean.getItemImageResid()); viewHolder.title.setText(bean.getItemContent()); viewHolder.content.setText(bean.getItemContent()); } return convertView; } // 避免重復的findViewById的操作 class ViewHolder{ public ImageView imageView; public TextView title; public TextView content; } }
/** * 創建設置每個Item的類 * Created by herd_youth on 2016/4/15. */ public class ItemBean { private int ItemImageResid; private String ItemTitle; private String ItemContent; public ItemBean(int itemImageResid, String itemTitle, String itemContent) { ItemImageResid = itemImageResid; ItemTitle = itemTitle; ItemContent = itemContent; } public int getItemImageResid() { return ItemImageResid; } public void setItemImageResid(int itemImageResid) { ItemImageResid = itemImageResid; } public String getItemTitle() { return ItemTitle; } public void setItemTitle(String itemTitle) { ItemTitle = itemTitle; } public String getItemContent() { return ItemContent; } public void setItemContent(String itemContent) { ItemContent = itemContent; } }
在 Android 的 OnScrollListener 整個事件我主要分析下他的執行順序: 實現滾動事件的監聽接口 new AbsListView.OnScrol
本來不想寫關於struts2的學習筆記了,由於感覺關於struts2的理論知識比較簡單,所以才打算不寫,但是在學習過程中,特別是在Myeclipse中編碼練習的時候,遇到
1.ViewPager簡單使用ViewPager是android擴展包android.support.v4 裡的一個繼承與ViewGroup組件,通過布局管理器可以實現左
Batterystats & Battery Historian Walkthrough Battery Historian Charts Android應用的