Android ListView 应用解析
jopen
12年前
在android开发中ListView是比较常用的组件,它以列表的形式展示具体内容,并且能够根据数据的长度自适应显示。抽空把对ListView的使用做了整理,并写了个小例子,如下图。
列表的显示需要三个元素:
1.ListVeiw 用来展示列表的View。
2.适配器 用来把数据映射到ListView上的中介。
3.数据 具体的将被映射的字符串,图片,或者基本组件。
根据列表的适配器类型,列表分为三种,ArrayAdapter,SimpleAdapter和SimpleCursorAdapter
现在项目的结构如下图所示:
main.xml如下所示:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:text="@string/name" android:layout_width="120dp" android:layout_height="wrap_content" /> <TextView android:text="@string/phone" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> <ListView android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/listView" /> </LinearLayout>
item.xml如下图所示:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:id="@+id/name" android:layout_width="120dp" android:layout_height="wrap_content"/> <TextView android:id="@+id/phone" android:layout_width="fill_parent" android:layout_height="wrap_content"/> </LinearLayout>
string.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello World, MainActivity!</string> <string name="app_name">数据库应用</string> <string name="name">姓名</string> <string name="phone">电话</string> </resources>
cn.roco.db.domain.Person代码如下:
package cn.roco.db.domain; public class Person { public Person(Integer id, String name, String phone) { this.id = id; this.name = name; this.phone = phone; } public Person(String name, String phone) { this.name = name; this.phone = phone; } public Person() { } private Integer id; private String name; private String phone; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @Override public String toString() { // TODO Auto-generated method stub return "Person[id="+id+",name="+name+",phone="+phone+"]"; } }
package cn.roco.db.service; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class DBOpenHelper extends SQLiteOpenHelper { public DBOpenHelper(Context context) { super(context,"roco.db", null, 2); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE person(personid integer primary key autoincrement,name varchar(20),phone varchar(20))"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("ALTER TABLE person ADD phone VARCHAR(12) NULL"); } }
package cn.roco.db.serice; import java.util.List; import cn.roco.db.domain.Person; public interface IPersonService { public void save(Person person); public void delete(Integer id); public void update(Person person); public Person find(Integer id); public List<Person> getScrollData(int offset,int maxResult); public long getCount(); }
package cn.roco.db.serice.imp; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import cn.roco.db.domain.Person; import cn.roco.db.serice.IPersonService; import cn.roco.db.service.DBOpenHelper; public class PersonServiceImp implements IPersonService { private DBOpenHelper dbOpenHelper; public PersonServiceImp(Context context) { this.dbOpenHelper = new DBOpenHelper(context); } /** * 添加记录 * @param person */ @Override public void save(Person person) { SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); db.execSQL("insert into person(name,phone) values(?,?)", new Object[] { person.getName(), person.getPhone() }); } /** * 添加记录 * @param id */ @Override public void delete(Integer id) { SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); db.execSQL("delete from person where personid=?", new Object[] { id }); } /** * 更新记录 * @param person */ @Override public void update(Person person) { SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); db.execSQL( "update person set name=?,phone=? where personid=?", new Object[] { person.getName(), person.getPhone(), person.getId() }); } /** * 查询记录 * @param id */ @Override public Person find(Integer id) { SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); Cursor cursor = db.rawQuery( "select personid,name,phone from person where personid=?", new String[] { id.toString() }); if (cursor.moveToFirst()) { int personid = cursor.getInt(cursor.getColumnIndex("personid")); String name = cursor.getString(cursor.getColumnIndex("name")); String phone = cursor.getString(cursor.getColumnIndex("phone")); return new Person(personid, name, phone); } cursor.close(); return null; } /** * 分页获取几率 * @param offset 跳过前面多少条记录 * @param maxResult 每页获取多少条记录 * @return */ @Override public List<Person> getScrollData(int offset, int maxResult) { List<Person> persons = new ArrayList<Person>(); SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); Cursor cursor = db .rawQuery( "select * from person order by personid asc limit ?,?", new String[] { String.valueOf(offset), String.valueOf(maxResult) }); while (cursor.moveToNext()) { int personid = cursor.getInt(cursor.getColumnIndex("personid")); String name = cursor.getString(cursor.getColumnIndex("name")); String phone = cursor.getString(cursor.getColumnIndex("phone")); persons.add(new Person(personid, name, phone)); } cursor.close(); return persons; } public Cursor getCursorScrollData(int offset, int maxResult) { List<Person> persons = new ArrayList<Person>(); SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); Cursor cursor = db .rawQuery( "select personid as _id, name, phone from person order by personid asc limit ?,?", new String[] { String.valueOf(offset), String.valueOf(maxResult) }); return cursor; } /** * 获取记录总数 * @return */ @Override public long getCount() { SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); Cursor cursor = db.rawQuery("select count(*) from person ", null); cursor.moveToFirst(); long result = cursor.getLong(0); cursor.close(); return result; } }
MainActivity
package cn.roco.db; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import cn.roco.db.adapter.PersonAdapter; import cn.roco.db.domain.Person; import cn.roco.db.serice.imp.PersonServiceImp; import android.app.Activity; import android.database.Cursor; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.SimpleCursorAdapter; import android.widget.Toast; public class MainActivity extends Activity { private ListView listView; private PersonServiceImp personService; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); personService = new PersonServiceImp(this); listView = (ListView) this.findViewById(R.id.listView); listView.setOnItemClickListener(new ItemClickListener()); showByCursor(); // showByList(); // showByPersonAdapter(); } /** *配置一个响应事件类 */ private final class ItemClickListener implements OnItemClickListener{ @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { ListView lView=(ListView) parent; /** * 对应自定义适配器 */ // Person person= (Person) lView.getItemAtPosition(position); // Toast.makeText(getApplicationContext(), "id="+person.getId(), 1).show(); /** * 对应游标适配器 */ Cursor cursor=(Cursor) lView.getItemAtPosition(position); int personid=cursor.getInt(cursor.getColumnIndex("_id")); Toast.makeText(getApplicationContext(), "id="+personid, 1).show(); } } //使用自定义的适配器PersonAdapter private void showByPersonAdapter() { List<Person> persons=personService.getScrollData(0, 30); PersonAdapter adapter=new PersonAdapter(this, persons, R.layout.item); listView.setAdapter(adapter); } //使用游标适配器SimpleCursorAdapter private void showByCursor() { Cursor cursor = personService.getCursorScrollData(0, 30); /** * 注意该适配器中的cursor必须要包含 _id 字段 * 解决方法:select personid as _id ..... */ SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.item, cursor, new String[] { "name", "phone" }, new int[] { R.id.name, R.id.phone }); listView.setAdapter(adapter); } //使用简单适配器SimpleAdapter private void showByList() { List<Person> persons = personService.getScrollData(0, 30); /** * 将取出来的数据封装到 List<HashMap<String, Object>> 中 */ 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("id", person.getId()); data.add(item); } /** * 设置好适配器对应的关系 */ SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.item, new String[] { "name", "phone" }, new int[] { R.id.name, R.id.phone }); listView.setAdapter(adapter); } }
自定义的Adapter
package cn.roco.db.adapter; import java.util.List; import cn.roco.db.R; import cn.roco.db.domain.Person; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; public class PersonAdapter extends BaseAdapter { private List<Person> persons; //绑定数据 private int resouce ; //绑定的条目节目 private LayoutInflater inflater; public PersonAdapter(Context context, List<Person> persons,int resouce) { this.persons=persons; this.resouce=resouce; inflater= (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override //得到总的数量 public int getCount() { return persons.size(); //数据总数 } @Override //根据ListView位置返回View public Object getItem(int position) { return persons.get(position); } @Override //根据ListView位置得到List中的ID public long getItemId(int position) { return position; } @Override //根据位置得到View对象 public View getView(int position, View convertView, ViewGroup parent) { TextView nameView=null; TextView phoneView=null; if (convertView==null) { convertView=inflater.inflate(resouce, null);//生成条目节目对象 //得到条目中的子组件 nameView=(TextView) convertView.findViewById(R.id.name); phoneView= (TextView) convertView.findViewById(R.id.phone); ViewCache cache=new ViewCache(); cache.nameView=nameView; cache.phoneView=phoneView; convertView.setTag(cache); }else{ ViewCache cache=(ViewCache) convertView.getTag(); nameView=cache.nameView; phoneView=cache.phoneView; } //从list对象中为子组件赋值 实现数据绑定 Person person= persons.get(position); nameView.setText(person.getName()); phoneView.setText(person.getPhone()); return convertView; } /** * 定义的缓存类 */ private final class ViewCache{ public TextView nameView; public TextView phoneView; } }