Cursor记录集游标、ListView和SimpleCursorAdapter、ListView数据动态更新
Email:[email protected]
为什么要把Cursor、ListView、SimpleCursorAdapter这三个放在一起来讲呢?实在是因为在使用的时候,这三个太紧密相关了。
环境:
IDE:Android Studio
JDK:1.8
系统:win7 64位
一、Cursor
在android系统中使用SQLite数据库,那么Cursor就会经常使用,使用方式大概如下:
SQLiteDatabase db; //... String sql = "select * from 表"; Cursor cursor = db.rawQuery(sql,null);
首先,我们要使用Cursor记录集游标,就必须知道查询语句中表的字段名、数据类型。
使用方法:
if(cursor.moveToFirst()==false) return;
使用方法:
List<Map<String,Object>> list = new ArrayList<Map<String,Object>>(); Map<String,Object> map; while (cursor.moveToNext()) { map = new HashMap<String, Object>(); map.put("name",cursor.getString(cursor.getColumnIndex("name"))); map.put("phone",cursor.getString(cursor.getColumnIndex("phone"))); map.put("_id",cursor.getString(cursor.getColumnIndex("_id"))); list.add(map); }
使用方法:
结合isBeforeFirst()、isAfterLast()、moveToNext()三个方法,我们将可以通过for循环来遍历整个记录集
for(cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()) { //获取数据,和while()循环一样; }
还有一些其他方法吧,暂时没有用过,所以就不罗列了,上面已经把非常常用的方法列举了。
二、ListView和SimpleCursorAdapter
当我们从数据库中查到了数据以后,一般就会用作界面显示,那么ListView就会经常用到。那么我分三部分讲:1)用于显示数据适配器;2)数据库中数据更新后,ListView也更新。首先我们需要三个元素:ListView、adapter即适配器,用于将数据映射到ListView中、数据。
1)常用方法,根据适配器不一样,或者数据不一样,我们要选择的方法也不一样。一般分为三种:ArrayAdapter、SimpleAdapter和SimpleCursorAdapter。第一种最简单 ,只能用于显示一行文字,第二种扩展性更好,支持自定义,第三种主要适用于Cursor记录集游标。对于第一种适配器,本人没有上代码测试过,所以就不讲了。
public class ShowAddressActivity extends ListActivity { private AddressDAO addressDAO; private SimpleAdapter adapter; private Cursor cursor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //查数据库返回所有联系人 addressDAO = new AddressDAO(this); cursor = addressDAO.query(); List<Map<String,Object>> list = new ArrayList<Map<String,Object>>(); Map<String,Object> map; //遍历数据 while (cursor.moveToNext()) { map = new HashMap<String, Object>(); map.put("name",cursor.getString(cursor.getColumnIndex("name"))); map.put("phone",cursor.getString(cursor.getColumnIndex("phone"))); map.put("_id",cursor.getString(cursor.getColumnIndex("_id"))); list.add(map); } adapter = new SimpleAdapter(this,list,R.layout.address_list,new String[]{"_id","name","phone"},new int[]{R.id.id,R.id.name,R.id.phone}); setAdapter(adapter);首先我们需要把查询的数据从cursor游标再次封装到有HashMap构成的list中,然后再使用new SimpleAdapter();将数据映射到xml文件中,完成适配:映射规则如下图:
public class ShowAddressActivity extends ListActivity { private AddressDAO addressDAO; private SimpleCursorAdapter adapter; private Cursor cursor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.show_address); //查数据库返回所有联系人 addressDAO = new AddressDAO(this); cursor = addressDAO.query(); adapter = new SimpleCursorAdapter(this,R.layout.address_list,cursor,new String[]{"_id","name","phone"},new int[]{R.id.id,R.id.name,R.id.phone}); ListView listView = (ListView)findViewById(android.R.id.list); listView.setAdapter(adapter); //.. }
其中涉及到了两个xml文件:show_address.xml和address_list.xml,布局代码如下:
(1)show_address.xml:包含一个搜索框、一个增加按钮和一个ListView<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" tools:context="com.s201525015.chen.addresslist.ShowAddressActivity"> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent" android:weightSum="1"> <EditText android:layout_width="279dp" android:layout_height="60dp" android:hint="搜索联系人" android:id="@+id/search" android:layout_weight="0.65" /> <Button android:layout_width="55dp" android:layout_height="45dp" android:text="增加" android:id="@+id/addButton" /> </LinearLayout> <ListView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@android:id/list"> </ListView> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/id" android:layout_weight="1" android:visibility="gone"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/name" android:layout_weight="1" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/phone" /> </LinearLayout> </LinearLayout>
这里也要提醒一个问题:findViewById(R.id.list)默认的是在当前页面中寻找id为list的控件,也就是说在setContentView(XXX),那么只会在XXX.xml文件中查找id为list的控件。如果我们setContentView(A),却需要获取B.xml中的控件就需要先指定页面,再查找:
指定页面为show_address.xml:
ListView listAddress = (ListView) View.inflate(this,R.layout.show_address,null).findViewById(android.R.id.list);
三、使用SimpleCursorAdapter,ListView数据更新
private class RefresList extends AsyncTask<Void,Void,Cursor> { protected Cursor doInBackground(Void... params) { Cursor newCursor = addressDAO.query(); return newCursor; } protected void onPostExecute(Cursor newCursor) { adapter.changeCursor(newCursor); cursor.close(); cursor = newCursor; } }
四、提示
在这里重点提示一下SimpleAdapter和SimpleCursorAdapter,这两个适配器的重要区别:
1)如果使用后者,数据库表中的字段必须有_id,是否一定要为主键,我不敢确定。
2)前者映射时数据类型是map构成的list,后者是cursor。