1.概述
CursorAdapter适用于使用Cursor加载ListView的数据的情况,例如建立一个列表显示数据库数据,或使用内容提供器显示其他应用数据等一系列需要使用游标来加载数据的情况。
CursorAdapter继承自BaseAdapter,直接子类是ResourceCursorAdapter,间接子类是SimpleCursorAdapter(适用于将游标中的列映射到XML文件中定义的TextView或ImageView),是抽象类,使用时需要用一个类去继承它,并且加载的Cursor里面必须包含一列名为”_id”。
注:本文适用于已经至少简单了解游标的用法的朋友
2.必须重写的方法
1.构造方法
以接下来将有的一个例子来讲,会写一个类MyCursorAdapter继承CursorAdapter,构造方法就是
public MyCursorAdapter(Context context, Cursor c) {
super(context, c, false);
}
super的三个参数分别代表:
第一参数 context:上下文
第二参数 c:携带需要显示数据地游标
第三参数 false:如果为true,那么适配器每次更改时都会在光标上调用requery(),以便始终显示最新数据。在这里使用真实是不鼓励的,所以用false。
2.public View newView(Context context, Cursor cursor, ViewGroup parent)
定义每个ListView的item加载的View,或者说 这里可以绑定每个item的layout.这里可以通过以下方式来写:
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(android.R.layout.
simple_list_item_1,
parent, false);
}
其中android.R.layout. simple_list_item_1是一个有一个id为android.R.id.text1的TextView的布局
3.public void bindView(View view, Context context, Cursor cursor)
这个方法将现有视图绑定游标指向的数据,用来向ListView自项绑定数据,参数中:cursor用来是取数据,将数据绑到view的自View上。每次调用该方法时,cursor已经移动到了正确的位置,无需关心游标的移动的问题。依旧放一个本文最后完整的例子的片段:
public void bindView(View view, Context context, Cursor cursor) {
TextView itemText=view.findViewById(android.R.id.text1);
itemText.setText(cursor.getString(cursor.
getColumnIndex("name")));
}
cursor是一个数据库里面表的一个游标,表中有一列叫“name”,将数据取出,加载到子项里的view的TextView里。
3.刷新数据
可以使用swapCursor(Cursor)或changeCursor(Cursor)刷新数据,他参数都是一个新的Cursor对象。它们的区别主要是swapCursor返回一个没有关闭的原先的Cursor对象,而changeCursor返回的将是一个关闭的原Cursor对象。
需要注意的是
swapCursor返回先前设置的游标,如果没有游标,则返回null。如果给定的新游标与先前设置的游标是相同的实例,则返回null。
changeCursor会关闭原游标。
4.完整的demo
1.数据库帮助类SQLiteOpenHelper
package com.example.test.cursor_adapter;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;
/**
* Created by HeTingwei on 2018/5/27.
* 一个用来存数据的数据库
*/
public class MyDatabaseHelper extends SQLiteOpenHelper {
public final static String TABLE_NAME = " test_table";
private static final String CREATE_DATABASE = "create table "+TABLE_NAME+"(" +
"_id integer ," +
"name text)";
Context context;
public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory,
int version) {
super(context, name, factory, version);
this.context = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_DATABASE);
Toast.makeText(context, "数据库已创建", Toast.LENGTH_SHORT).show();
//添加数据
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
2.加载ListView的activity:BasicCursorAdapterActivity,其中有一个的CursorView的子类MyCursorAdapter
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.example.test.R;
import static com.example.test.cursor_adapter.MyDatabaseHelper.TABLE_NAME;
public class BasicCursorAdapterActivity extends AppCompatActivity {
private ListView mList;
Cursor myCursor;
SQLiteDatabase db;
MyCursorAdapter myCursorAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_basic_cursor_adapter);
initData();
initView();
}
//单击按钮添加新数据
public void click(View view) {
ContentValues values = new ContentValues();
values.put("name","cqg");
db.insert(TABLE_NAME, null, values);
values.clear();
myCursor = db.query(TABLE_NAME, null, null, null, null, null, null, null );
//这里不需要返回cursor对象所以使用changeCursor(它会关闭原cursor对象)
myCursorAdapter.changeCursor(myCursor);
}
//创建数据库,同时获取游标
private void initData() {
MyDatabaseHelper dbHelper = new MyDatabaseHelper(this,"Test_database",null,1);
db = dbHelper.getWritableDatabase();
myCursor = db.query(TABLE_NAME, null, null, null, null, null, null, null );
ContentValues values = new ContentValues();
if (myCursor != null && myCursor.getCount() == 0) {
for (int i = 0; i < 5; i++) {
values.put("name", "htw" + i);
db.insert(TABLE_NAME, null, values);
values.clear();
}
myCursor.close();
}
myCursor = db.query(TABLE_NAME, null, null, null, null, null, null, null );
values.clear();
}
private void initView() {
mList = (ListView) findViewById(R.id.list);
myCursorAdapter=new MyCursorAdapter(this, myCursor);
mList.setAdapter(myCursorAdapter);
}
//回收
@Override
protected void onDestroy() {
super.onDestroy();
if(db!=null)
db.close();
if(myCusor!=null)
myCursor.close();
}
class MyCursorAdapter extends CursorAdapter {
public MyCursorAdapter(Context context, Cursor c) {
super(context, c, false);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {//绑定布局文件
return LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1,
parent, false);
}
//绑定数据
@Override
public void bindView(View view, Context context, Cursor cursor) {
TextView itemText=view.findViewById(android.R.id.text1);
itemText.setText(cursor.getString(cursor.getColumnIndex("name")));
}
}
}
3.activity的布局文件activity_basic_cursor_adapter.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.test.cursor_adapter.BasicCursorAdapterActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:layout_marginTop="16dp"
android:onClick="click"
android:text="更新数据"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"></ListView>
</android.support.constraint.ConstraintLayout>
4.效果