第一次寫博客,希望大家喜歡
先來簡單的創建撒~然後再慢慢優化,發出來供大家交流經驗,嘿嘿
先說說listview的原理撒
其實listview 可以看做一個框架子,他有一個整體的框框,還有一個一個的行,
就像這樣(圖是我自己畫的。。。不知道這樣理解夠不夠完善,但是寫代碼的時候就是這個思路了)
1、首先創建項目咯~
2、在activity_main.xml中拖入ListView的組件(組件在composite中)
剛加進去的代碼是這樣的
<ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" > </ListView>
一定要注意將layout_height的值改爲match_parent,否則在運行時會出現跳行的情況(具體原因是:在activity加載ListView的時候,如果ListView的高度爲適應內容,那麼每次加載行的時候都會重新運算一遍,所以如果打日誌的話 會發現 原本只有6行的顯示,卻打了好多行日誌)
3、在layout裏面新建個行佈局(佈局就隨便了,我一般用RelativeLayout,如果是只需要一個文本的話,只用一個TextView 也是可以的)
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:text="Large Text" android:textAppearance="?android:attr/textAppearanceLarge" /> </RelativeLayout>
也可以直接這樣的
<TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:text="Large Text" android:textAppearance="?android:attr/textAppearanceLarge" > </TextView>
ok UI(佈局文件) 這樣就可以了 簡單的來麼
現在來看代碼
在MainActivity.java中的onCreate方法中加入先讀取layout中的listview
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView listView = (ListView) findViewById(R.id.listView1);//讀取listView的 BaseAdapter adapter = new BaseAdapter()//創建一個適配器,這是一個內部類了 { @Override public View getView(int position, View convertView, ViewGroup parent) { /* * getView 加載每一行的時候系統會自動調用這個方法,所以要在這個方法中創建當前行樣式 * 主要參數:1、position:當前行的id * 2、convertView:當listview滑動式緩存消失的行佈局 * 3、parent:The parent that this view will eventually be attached to * (額這是官方解釋了。。。sorry~ 沒用過具體怎麼樣我也不太清楚) */ //開始創建行, LayoutInflater inflater = getLayoutInflater(); RelativeLayout layout = (RelativeLayout) inflater.inflate(R.layout.list_item, null); //以上兩行代碼 獲取每行的佈局 //有了layout就可以獲取當前行的組件了,組件拿到了,也就可以設置該組件的值了 TextView textView = (TextView) layout.findViewById(R.id.textView1); textView.setText("title"+position);//前面有說過position是代表當前行的id 從零開始計數 return layout;//一定要記得將創建好的行佈局 返回給 系統,不然 你講神馬都看不到了 } @Override public long getItemId(int position)//這個方法還有getItem()方法 我都沒有用過,具體什麼效果 //大家可以試試撒 { return 0; } @Override public Object getItem(int position) { return null; } @Override public int getCount()//設置要創建多少行 { return 10;//表示要創建10行 } }; listView.setAdapter(adapter);//將創建的適配器(adapter)放到listview中 }
這樣就ok了 一個簡單的listview 就搞好了,可以在模擬器上運行下試試撒~
但是這樣的代碼還是有很多問題的,你可以在getView中打印下日誌,輸出創建的layout,你就會發現竟然每一行的layout都是新的,這樣的話很消耗系統資源,(10行可能太少了,多搞點,在拖動的時候 就會發現了,寫多少行,就給你高多少個layout)
所以android官方 推薦用convertView+ViewHolder的方式來提高性能,這樣系統只會創建當前頁顯示數量+1個layout,就可以是layout複用,其他的行都只用創建好的layout就可以了
優化代碼如下:
class ViewHolder{//ViewHolder自己創建就好了,這是內部類,因爲當前類只要MainActivity使用就好了,所以不需要新建一個class文件了 TextView mTextView;//官方的源代碼中,成員變量就是這樣寫的 //(前面加個m這樣只要看到他就知道這個變量是成員變量了,後面名字隨便) } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView listView = (ListView) findViewById(R.id.listView1);//讀取listView的 BaseAdapter adapter = new BaseAdapter()//創建一個適配器,這是一個內部類了 { @Override public View getView(int position, View convertView, ViewGroup parent) { /* * getView 加載每一行的時候系統會自動調用這個方法,所以要在這個方法中創建當前行樣式 * 主要參數:1、position:當前行的id * 2、convertView:是一個緩存,存取listview滑動時緩存最先消失的那個行佈局, * 後面顯示的行就可以複用這個convertView了,這樣就可以達到複用的效果,節省資源 * * 3、parent:The parent that this view will eventually be attached to * (額這是官方解釋了。。。sorry~ 沒用過具體怎麼樣我也不知道) */ //開始創建行, RelativeLayout layout = null; ViewHolder holder = null; if(convertView == null){//當緩存爲空是 創建layout LayoutInflater inflater = getLayoutInflater(); layout = (RelativeLayout) inflater.inflate(R.layout.list_item, null); //以上兩行代碼 獲取每行的佈局 holder = new ViewHolder();//創建holder; holder.mTextView = (TextView) layout.findViewById(R.id.textView1);//講獲取到的行組件放入holder中 /*這裏存在一個問題 layout是兩個東西怎樣將 layout和holder聯繫在一起呢? *不用擔心,View類提供了一個方法,setTag(Object obj); *這個方法可以將holder像一個物品一樣放入一個叫Tag 的袋子裏 *這樣就可以 複用 行佈局和佈局中的組件了 **/ layout.setTag(holder); }else{//有緩存時 就直接將緩存中的convertView給layout就好了 layout = (RelativeLayout) convertView; holder = (ViewHolder) layout.getTag(); } //更新組件內容 holder.mTextView.setText("title"+position);//前面有說過position是代表當前行的id 從零開始計數 return layout;//一定要記得將創建好的行佈局 返回給 系統,不然 你講神馬都看不到了 } @Override public long getItemId(int position) { return 0; } @Override public Object getItem(int position) { return null; } @Override public int getCount()//設置要創建多少行 { return 10;//表示要創建10行 } }; listView.setAdapter(adapter);//將創建的適配器(adapter)放到listview中 }
呵呵 優化好啦,這時候可以試試在打日誌看看,