android_ListView

第一次寫博客,希望大家喜歡

先來簡單的創建撒~然後再慢慢優化,發出來供大家交流經驗,嘿嘿


先說說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中
}

呵呵 優化好啦,這時候可以試試在打日誌看看,

源代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章