1. 程式人生 > >Android採用ListView實現資料列表顯示

Android採用ListView實現資料列表顯示

(1)、首先設計介面,使用上面一個數據庫專案,將資料庫中的所有資料用ListView顯示在螢幕上:新建一個佈局檔案item.xml

<TextView

       android:layout_width="120dp"

       android:layout_height="wrap_content"

       android:id="@+id/name"

       />

    <TextView

       android:layout_width="150dp"

       android:layout_height="wrap_content"

       android:id="@+id/phone"

       />

     <TextView

       android:layout_width="fill_parent"

       android:layout_height="wrap_content"

       android:id="@+id/amount"

       />

Main中:

<ListView

       android:layout_width="fill_parent"

       android:layout_height="fill_parent"

       android:id="@+id/listView"

       ></ListView>

(2)、呼叫取得分頁資料方法獲得資料庫中的內容,假設取得20條資料,返回一個集合。

(3)、接下來要在Activity當中使用介面卡將資料與顯示介面控制元件進行繫結,常用的介面卡有SimpleAdapter與SimpleCursorAdapter,另外還有自定義介面卡,首先建立介面卡物件,內部有個引數,第一個是上下文物件,第二個是要繫結的資料,可以使用一個HashMap泛型進行儲存,對persons進行迭代。放入泛型集合中。第三個引數是讓我們指定資料繫結到哪一個條目上,我們希望繫結到item.xml這個介面上,第四個引數是(from引數),即指定把哪一項資料繫結到哪一個控制元件上,為String型別,第四個引數是控制元件位置(為int型),最後呼叫APIsetAdapter()進行繫結。

(4)、set方法的內部過程:首先adapter會呼叫getCount()方法用於得到資料總數,然後會根據每個條目的高度計算出在一個窗口裡面應該顯示多少個條目,假設每頁顯示7個條目,接下來進行迭代,使用for迴圈:

For(inti=0;i<perpage;i++){

接著呼叫getView(position,convertView,parent)方法用於每個條目的介面,最後進行介面顯示的操作。

//convertView是原先快取的頁面,當翻到後面時,會使用以前的View物件進行快取。

}

原始碼:

private void show() {

    List<Person>persons=service.getScrollData(0,40);

    List<HashMap<String,Object>> data=new ArrayList<HashMap<String,Object>>();

    for(Person person:persons){

        HashMap<String, Object>item=new HashMap<String, Object>();

        item.put("name",person.getName());

        item.put("phone",person.getPhone());

        item.put("amount",person.getAmount());

        item.put("id",person.getId());

        data.add(item);

    }

    SimpleAdapter adapter=newSimpleAdapter(getApplicationContext(), data,R.layout.item,newString[]{"name","phone","amount"}, newint[]{R.id.name,R.id.phone,R.id.amount});

    listView.setAdapter(adapter);

    }


(5)、接下來將使用另外一種介面卡實現此功能:SimpleCursorAdapter

private void show2() {

         Cursorcursor=service.CursorgetScrollData(0, 40);

         @SuppressWarnings("deprecation")

         SimpleCursorAdapteradapter=new SimpleCursorAdapter(getApplicationContext(), R.layout.item, cursor,new String[]{"name","phone","amount"}, newint[]{R.id.name,R.id.phone,R.id.amount});

         listView.setAdapter(adapter);

    }

但執行後報錯: Caused by:java.lang.IllegalArgumentException: column '_id' does not exist。

這時候開啟CursorAdapter的最終父類原始碼發現,想要使用這個類,必須包含一個叫’_id’的欄位,否則就不能工作。

The Cursor must include a column named"_id" or this class will not work.


(6)、那麼如何解決這個錯誤呢,有兩種解決方案,第一種:在資料庫中將主鍵名更改為_id,即可解決

第二種:如果不希望修改表結構,可以通過修改查詢結果集實現,即修改sql語句的欄位名:

public Cursor CursorgetScrollData(intoffset,int maxResult){

         List<Person>list=new ArrayList<Person>();

         SQLiteDatabasedb=openHelper.getReadableDatabase();

         Cursorcursor=db.rawQuery("SELECT persionidas _id,name,phone,amount FROM person order by persionid asc limit ?,?",new String[]{String.valueOf(offset),String.valueOf(maxResult)});

         returncursor;

    }


(7)、使用自定義介面卡實現資料的繫結:

1、建立PersonAdapter繼承BaseAdapter抽象類

2、這個抽象類裡提供了一個getCount()方法用來統計資料的條數,而我們傳進來的資料為List<Person>格式,則需要建立一個該物件用來儲存繫結的資料,並通過構造器為其賦值。

3、建立一個int型的變量表示要繫結的條目介面,也通過構造器獲得。

4、getView()方法用來獲取介面,這裡需要注意的是,當介面上出現一個條目時,安卓系統就會主動建立一個該條目的View物件,當翻過一頁之後,已經建立的條目不會重新進行建立,系統會重用他們的View物件進行顯示,即在這裡實現了一個快取的功能。

5、在這裡需要使用到一個類LayoutInflater,可以使用一個XML檔案生成類物件,屬於系統內建服務,名為佈局填充服務,需要使用上下文物件的getSystemService(Context.InflaterService)進行呼叫.

6、接著呼叫填充器的inflate(resource,null)方法,返回一個View型別的值。

7、接下來實現資料的繫結,呼叫該View屬性的findViewById(),找到各自對應的控制元件。

8、接下來對控制元件賦值,需要用到position這引數值,表示該條目所繫結的資料在集合中的索引值。接著呼叫各自的setText方法。

原始碼:

public class PersonAdapter extendsBaseAdapter {

    privateList<Person> persons;

    privateint resource;//繫結的條目介面

    privateLayoutInflater inflater;//佈局填充器

    publicPersonAdapter(List<Person> persons, int resource,Context context) {

         this.persons= persons;

         this.resource= resource;

         inflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    }

    @Override

    publicint getCount() {//獲取資料數量

         intcount=persons.size();

         returncount;

    }

    @Override

    publicObject getItem(int position) {

         returnpersons.get(position);

    }

    @Override

    publiclong getItemId(int position) {

         returnposition;

    }

    @Override

    publicView getView(int position, View convertView, ViewGroup parent) {

         if(convertView==null){

             convertView=inflater.inflate(resource,null);//生成條目介面物件

         }

         TextViewnameView=(TextView) convertView.findViewById(R.id.name);

         TextViewphoneView=(TextView) convertView.findViewById(R.id.phone);

         TextViewamountView=(TextView) convertView.findViewById(R.id.amount);

         Personperson=persons.get(position);

         //資料繫結

         nameView.setText(person.getName());

         phoneView.setText(person.getPhone());

         amountView.setText(person.getAmount().toString());

         returnconvertView;

    }

}


(9)、如果使用者點選的某一條目,如何獲得繫結的詳細資料?

1、為listView設定一個條目點選事件setItemOnClickListener()

2、實現onItemClick(AdapterView parent,View view,int position,long id),第一個引數表示當前被點選條目所在的listView,第二個是代表當前所點選的View物件,第三個引數表示當前點選條目所繫結資料在集合中的索引值,最後一個id很少用到。

原始碼:

public class ItemClick implementsOnItemClickListener {

         @Override

         publicvoid onItemClick(AdapterView<?> parent, View view, int position,long id){

             ListViewlview=(ListView) parent;

             Personperson=(Person) lview.getItemAtPosition(position);

             Toast.makeText(getApplicationContext(),person.getName().toString(), Toast.LENGTH_LONG).show();

         }

    }


(10)、如果返回值是Cursor型別的話:

ListView lview=(ListView) parent;

             Cursorcursor=(Cursor) lview.getItemAtPosition(position);

             intpersonid=cursor.getInt(cursor.getColumnIndex("_id"));

             Toast.makeText(getApplicationContext(),personid+"", Toast.LENGTH_LONG).show();

 

(11)、然而做到這裡,其實本程式的效能比不是很好,因為每一次翻頁都會去查詢控制元件,因此可以通過內部類進行優化:

public View getView(int position, ViewconvertView, ViewGroup parent) {

         TextViewnameView=null;

         TextViewphoneView=null;

         TextViewamountView=null;

         if(convertView==null){

             convertView=inflater.inflate(resource,null);//生成條目介面物件

          nameView=(TextView)convertView.findViewById(R.id.name);

          phoneView=(TextView)convertView.findViewById(R.id.phone);

         amountView=(TextView)convertView.findViewById(R.id.amount);

         ViewCache cache=new ViewCache();

             nameView=cache.nameView;

             phoneView=cache.phoneView;

             amountView=cache.amountView;

             convertView.setTag(cache);

         }else{

             ViewCachecache=(ViewCache) convertView.getTag();

             nameView=cache.nameView;

             phoneView=cache.phoneView;

             amountView=cache.amountView;

         }

         Personperson=persons.get(position);

         //資料繫結

         nameView.setText(person.getName());

         phoneView.setText(person.getPhone());

         amountView.setText(person.getAmount().toString());

         returnconvertView;

    }

private final class ViewCache{

         publicTextView nameView;

         publicTextView phoneView;

         publicTextView amountView;

    }