天天看點

android_ListView

第一次寫部落格,希望大家喜歡

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

先說說listview的原理撒

其實listview 可以看做一個架構子,他有一個整體的框框,還有一個一個的行,

就像這樣(圖是我自己畫的。。。不知道這樣了解夠不夠完善,但是寫代碼的時候就是這個思路了)

android_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中
}