2 Tìm hiều và sử dụng Content Provider:
2.4.3 Ví dụ về xây dựng một Content Provider:
Bây giờ ta sẽ thiết kế một ứng dụng lấy với cơ sở dữ liệu chỉ là tạo ra 1 mã ID tự động và người dùng nhập tên vào trong EditText sau đó lưu xuống cơ sở dữ liệu SQLite. Dữ liệu của ứng dụng này sẽ được chia sẻ với bên ngoài bằng cách xây dựng một Content Provider.
Đầu tiên, chúng ta tạo một lớp gọi làUserInfokế thừa lớpContentProvider như code sau:
public class UserInfo extends ContentProvider
{ … }
Trong lớp này ta tạo một số biến như tên của Content Provider, đường dẫn URI của Content Provider:
//ten cua Content Provider.
public static final String PROVIDER_NAME = "myandroid.net.User";
//duong dan URI cua Content Provider, cac ung dung khac se dung duong dan nay de
public static final Uri CONTENT_URI = Uri.parse("content://" + PROVIDER_NAME + "/users");
Sau đó chúng ta sẽ tạo uriMatcher để truy xuất Content Provider được dễ dàng: /cac chi so dung cho uriMatcher
public static final int USERS = 1;
public static final int USER_ID = 2; //khoi tao uriMatcher.
public static final UriMatcher uriMatcher;
static{
uriMatcher.addURI(PROVIDER_NAME, "users", USERS);
uriMatcher.addURI(PROVIDER_NAME, "users/#", USER_ID); }
Vì đây là một chương trình nhỏ và mô phỏng nên chúng ta không tao ra lớp DTO để thể hiện đối tượng nên mình sẽ tạo ra 2 biến để lấy và đưa giá trị và cơ sở dữ liệu:
//hai bien de nhan gia tri id va name de dua vao co so du lieu
public static final String sID = "ID";
public static final String sName = "Name";
Sau đó chúng tạo database như ở phần SQLite. Đến phần này mình xin khẳng định lại rằng Content Provider không phải là cách lưu trữ dữ liệu nên chúng ta phải sử dụng SQLite để lưu trữ dữ liệu. Mọi người có thể dùng các cách khác để lưu trữ, rất tiện lợi:
//tao database
private SQLiteDatabase gdb;
private static final String DATABASE_NAME = "USERDEMO";
private static final String TABLE_NAME = "USER";
private static final int DATABASE_VERSION = 1;
private static final String TABLE_CREATE = "CREATE TABLE [" + TABLE_NAME + "] (" +"[ID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," +
"[Name] TEXT NOT NULL)";
//su dung SQLtieOpenHelper de quan li viec luu du lieu
private static class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME , null, DATABASE_VERSION); }
@Override
public void onCreate(SQLiteDatabase db) { db.execSQL(TABLE_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int version_old, int
version_new) {
db.execSQL("DROP TABLE IF EXISTS titles"); onCreate(db);
} }
Sau đó chúng ta override các phương thức có trong lớp Content Provider mà chúng ta cần. Đầu tiên là phương thứconCreate, trong phương thức này chúng ta khởi tạo database và trả về true nếu tạo thành công, ngược lại là false:
@Override
public boolean onCreate() {
//lay context hien tai bang ham getContext Context context = this.getContext();
//tao database
DatabaseHelper dbHelper = new DatabaseHelper(context); //mo database de doc va ghi
gdb = dbHelper.getWritableDatabase();
return (gdb == null) ? false :true; }
Trong ví dụ demo này mình chỉ override hàm insert, hàm này nhận hai tham số là: o Uri uri: đường dân của Content Provider
o ContentValues values: giá trị cần đưa vào cơ sở dữ liệu, đối tượng này sẽ nhận các giá trị mà người dùng nhập vào
@Override
public Uri insert(Uri uri, ContentValues values) { //chen du lieu vao table cua database
long rowID = gdb.insert(TABLE_NAME, "", values); //neu chen thanh cong thi thuc hien
if(rowID > 0)
{
//tao mot dinh dang cho dong du lieu ban moi vua them vao
Uri mUri = ContentUris.withAppendedId(CONTENT_URI, rowID);
//khoi dong bang ContentResolver de doi tuong mUri tao thanh cong getContext().getContentResolver().notifyChange(mUri, null); return mUri;
}
throw new SQLException("Failed to insert new row into " + uri); }
Cuối cùng là hàmquery(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder)(). Hàm này:
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
//doi tuong dung de luu cac gia tri cua cau lenh truy van, gia cu moi khong de len gia tri cu
SQLiteQueryBuilder sqlBuilder = new SQLiteQueryBuilder(); //set doi tuong SQLiteQueryBuilder len bang can lay du lieu sqlBuilder.setTables(TABLE_NAME);
//su dung chuoi uriMatcher ma minh da tao, neu chuoi nay dan den vung du lieu cua table
//thi lay du lieu ra khoi table
if(uriMatcher.match(uri) == USER_ID)
sqlBuilder.appendWhere(sID + "=" + uri.getPathSegments().get(1)); //sap xep du lieu tang dan theo id
if(sortOrder == null || sortOrder == "") sortOrder = sID;
//tao cursor bang du lieu ma minh da lay ra
Cursor cur = sqlBuilder.query(gdb, projection, selection, selectionArgs, null, null, sortOrder);
//khoi dong ContentResolver de doi tuong uri duoc hoat dong va du lieu duoc du ra
cur.setNotificationUri(getContext().getContentResolver(), uri);
}
Tiếp đó chúng ta cần viết một số hàm trong lớp MainActivity.
Hàm thêm dữ liệu vào database bằng cách nhận dữ liệu từ giao diện GUI: //them mot du lieu moi vao table
private void onAdd() {
//lay ten do nguoi dung nhap vao EditText
String name = edtName.getEditableText().toString(); //day gia tri ten vao ContentValues
ContentValues values = new ContentValues(); values.put(UserInfo.sName, name);
//dua gia tri ContentValues vao co so du lieu thong qua duong dan
Uri uriInsert = getContentResolver().insert(UserInfo.CONTENT_URI, values); //hien thong bao neu them du lieu thanh cong
if(uriInsert != null)
{
Toast.makeText(this, "User's added", Toast.LENGTH_SHORT).show(); }
}
Hàm lấy toàn bộ dữ liệu trong cơ sở dữ liệu và hiển thị lên giao diện: //ham hien thi toan bo du lieu
@SuppressWarnings("deprecation")
private void onDisplay() {
StringBuilder sb = new StringBuilder(); Uri uri = UserInfo.CONTENT_URI;
//khoi tao cursor voi duong dan uri va sap xep tang dan theo id Cursor c = managedQuery(uri, null, null, null, "ID desc");
if(c.moveToFirst()){ do{
String userRecord = "ID = " + c.getString(c.getColumnIndex(UserInfo.sID)) + " Name = " + c.getString(c.getColumnIndex(UserInfo.sName)); sb.append(userRecord); sb.append("\n"); }while(c.moveToNext()); } else { sb.append("Chua co du lieu"); }
((TextView)this.findViewById(R.id.txtDisplay)).setText(sb.toString()); }
Chúng ta cần thêm một số thông tin vào trong hàm AndroidMainfest.xml: <provider android:name = "UserInfo"
trong thẻ application. Tất cả source code và demo nằm trong thư mục DemoSeminar/Seminar_CreateContentProvider