Chức năng của content provider là gì?

Trong Android, Content Providers là một thành phần rất quan trọng phục vụ mục đích của cơ sở dữ liệu quan hệ để lưu trữ dữ liệu của các ứng dụng. Vai trò của Content Providers trong hệ thống Android giống như một kho lưu trữ trung tâm, trong đó dữ liệu của các ứng dụng được lưu trữ và nó tạo điều kiện cho các ứng dụng khác truy cập một cách an toàn và sửa đổi dữ liệu đó dựa trên yêu cầu của người dùng.

Hệ thống Android cho phép Content Providers lưu trữ dữ liệu ứng dụng theo một số cách. Người dùng có thể quản lý để lưu trữ dữ liệu ứng dụng như hình ảnh, âm thanh, video và thông tin liên hệ cá nhân bằng cách lưu trữ chúng trong Cơ sở dữ liệu SQLite, trong tệp hoặc thậm chí trên mạng. Để chia sẻ dữ liệu, Content Providers có một số quyền nhất định được sử dụng để cấp hoặc hạn chế quyền cho các ứng dụng khác can thiệp vào dữ liệu.

Các bài viết liên quan:

Content URI

Content URI (Định danh tài nguyên đồng nhất) là khái niệm chính của các Content Providers. Để truy cập dữ liệu từ Content Providers, URI được sử dụng như một chuỗi truy vấn.

Cấu trúc của Content URI: content://authority/optionalPath/optionalID

  • Chi tiết về các phần khác nhau của Content URI:
  1. content: // – Phần bắt buộc của URI vì nó thể hiện rằng URI đã cho là Content URI.
  2. authority – Ký hiệu tên của Content Providers như danh bạ, trình duyệt, v.v. Phần này phải là duy nhất cho mọi Content Providers.
  3. optionPath – Chỉ định loại dữ liệu được cung cấp bởi Content Providers. Điều cần thiết là phần này giúp các Content Providers hỗ trợ các loại dữ liệu khác nhau không liên quan đến nhau như tệp âm thanh và video.
  4. optionID – Nó là một giá trị số được sử dụng khi có nhu cầu truy cập vào một bản ghi cụ thể.

Nếu một ID được đề cập trong URI thì đó là URI dựa trên id, nếu không thì là URI dựa trên thư mục.

Xem thêm Activity android – mind map(sơ đồ tư duy)

Operations trong Content Providers

Có thể thực hiện bốn thao tác cơ bản trong Content Providers là Tạo, Đọc, Cập nhật và Xóa. Các hoạt động này thường được gọi là hoạt động CRUD.

  • Create: Thao tác tạo dữ liệu trong Content Providers.
  • Read: Được sử dụng để tìm nạp dữ liệu từ Content Providers.
  • Update: Để sửa đổi dữ liệu hiện có.
  • Delete: Để xóa dữ liệu hiện có khỏi bộ nhớ.

Hoạt động của Content Providers

Các thành phần giao diện người dùng của các ứng dụng android như Activity và Fragment sử dụng một đối tượng CursorLoader để gửi các yêu cầu truy vấn tới ContentResolver. Đối tượng ContentResolver gửi các yêu cầu (như tạo, đọc, cập nhật và xóa) đến ContentProvider với tư cách là một ứng dụng khách. Sau khi nhận được yêu cầu, ContentProvider sẽ xử lý yêu cầu đó và trả về kết quả mong muốn. Dưới đây là một sơ đồ để biểu diễn các quá trình này dưới dạng hình ảnh.

Tạo Content Providers

Sau đây là các bước cần thiết phải làm theo để tạo Content Providers:

  1. Tạo một lớp trong cùng một thư mục chứa tệp MainActivity và lớp này phải mở rộng lớp cơ sở ContentProvider.
  2. Để truy cập nội dung, hãy xác định địa chỉ URI của Content Providers.
  3. Tạo cơ sở dữ liệu để lưu trữ dữ liệu ứng dụng.
  4. Triển khai sáu phương thức trừu tượng của lớp ContentProvider.
  5. Đăng ký Content Providers trong tệp AndroidManifest.xml bằng thẻ <provider>.

Xem thêm Serializable và Parcelable trong android

Sau đây là sáu phương thức trừu tượng và mô tả của chúng mà chúng cần thiết để ghi đè như một phần của lớp ContentProvider:

Một phương thức chấp nhận các đối số và tìm nạp dữ liệu từ

bảng mong muốn. Dữ liệu được gỡ bỏ dưới dạng đối tượng con trỏ.

Để chèn một hàng mới trong cơ sở dữ liệu của Content provider.

Nó trả về URI nội dung của hàng được chèn.

Phương thức này được sử dụng để cập nhật các trường của một hàng hiện có.

Nó trả về số lượng hàng được cập nhật.

Phương pháp này được sử dụng để xóa các hàng hiện có.

Nó trả về số hàng đã bị xóa.

Phương thức này trả về Phần mở rộng Thư Internet Đa năng (MIME)

loại dữ liệu cho URI nội dung đã cho.

Khi Content provider được tạo, hệ thống Android sẽ gọi phương thức này ngay lập tức để khởi tạo trình cung cấp.

Mục đích chính của Content provider là phục vụ như một kho lưu trữ dữ liệu trung tâm, nơi người dùng có thể lưu trữ và có thể tìm nạp dữ liệu. Quyền truy cập của kho lưu trữ này cũng được cấp cho các ứng dụng khác nhưng theo cách an toàn để phục vụ các yêu cầu khác nhau của người dùng. Sau đây là các bước liên quan đến việc triển khai một Content provider. Trong Content provider này, người dùng có thể lưu trữ tên của người và có thể tìm nạp dữ liệu được lưu trữ. Hơn nữa, một ứng dụng khác cũng có thể truy cập vào dữ liệu được lưu trữ và có thể hiển thị dữ liệu.

Xem thêm 20 Content creation tool( công cụ tạo nội dung)

Ở phần 1, chúng ta đã tìm hiểu cách lưu trữ dữ liệu của một ứng dụng trong cơ sở dữ liệu SQLite. Trong trường hợp này, dữ liệu là “tài sản riêng” của ứng dụng và không thể được truy cập bởi các ứng dụng khác trong cùng một thiết bị Android.

Content Provider cung cấp cơ chế truy cập dữ liệu giữa các ứng dụng khác nhau trên cùng một thiết bị Android. Sử dụng Content Provider giống hình thức giao tiếp client/server trong đó ứng dụng truy cập dữ liệu đóng vai trò là client và Content Provider đóng vai trò là server.

Một Content Provider là một lớp con của lớp android.content.ContentProvider và việc tạo một Content Provider liên quan đến việc thực thi các phương thức sau:

Phương thức Chức năng
onCreate() Phương thức này được gọi khi một Content Provider được tạo lần đầu tiên và được dùng để thực thi các nhiệm vụ khởi tạo được yêu cầu bởi Content Provider.
query() Phương thức này được gọi khi một ứng dụng (client) yêu cầu dữ liệu được nhận từ Content Provider. Dữ liệu nhận được chứa trong một đối tượng Cursor.
insert() Phương thức này được gọi khi một hàng mới được thêm vào cơ sở dữ liệu Provider.
update() Phương thức này được gọi khi các hàng tồn tại sẵn cần được cập nhật đại diện cho client (ứng dụng).
delete() Phương thức này được gọi khi các hàng bị xóa từ một bảng.
getType() Trả về kiểu MIME của dữ liệu được lưu trữ bởi Content Provider.

 Content URI

Một thiết bị Android có thể chứa nhiều Content Providers, do đó, hệ thống phải cung cấp giải pháp để phân biệt các Content Providers. URI là một giải pháp cho phép xác định dữ liệu cụ thể với một Content Provider cụ thể.

Một URI có thể chia thành hai phần: phần xác định Content Provider (hay còn gọi là phần Authority) có hình thức giống một gói (package) trong ứng dụng Android, ví dụ:  com.example.mydbapp.myprovider; phần thứ hai xác định dữ liệu của Content Provider, ví dụ tham chiếu đến một bảng tên student trong Content Provider: com.example.mydbapp.myprovider/student hay xác định dữ liệu chi tiết hơn, ví dụ tham chiếu đến một hàng có giá trị ID là 3 trong bảng student: com.example.mydbapp.myprovider/student/3.

Có những URI có thể mở rộng đến nhiều cấp và lúc này chúng ta có thể dùng lớp UriMatcher.

Đối tượng ContentResolver

Truy cập đến một Content Provider đạt được nhờ đối tượng ContentResolver. Một ứng dụng có thể đạt được tham chiếu đến đối tượng ContentResolver bằng cách gọi phương thức getContentResolver(). Đối  tượng ContentResolver chứa các phương thức tương tự như của một Content Provider như insert(), query(), update(), v.v.

Phần tử <provider>

Một Content Provider, để được sử dụng trong hệ thống Android, phải được khai báo trong tập tin manifest với phần tử <provider>. Phần tử <provider> chứa hai thuộc tính quan trọng là:

  • android:authority: là URI với phần xác định nội dung của Content Provider
  • android:name: chứa tên lớp thực thi Content Provider

Dự án minh họa dùng Content Provider

Tạo dự án

– Tìm đến và sao chép thư mục ứng dụng SQLiteDemoApplication và đổi tên (mặc định là SQLiteDemoApplication-Copy) thành ContentProviderApplication.

– Đóng dự án hiện tại đang mở trên Android Studio bằng cách chọn File > Close Project. Trong cửa sổ Welcome to Android Studio chọn Open an existing Android Studio project:

– Trong Open File or Project tìm đến dự án ContentProviderApplication và nhấn OK

Thêm gói Content Provider

Thêm gói mới bằng cách vào app > java và nhấn chuột phải vào thư mục java chọn New > Package

– Trong hộp thoại Choose Destination Directory chọn …\app\source\main\java và nhấn OK

– Trong cửa sổ New Package, nhập tên gói là com.ngocminhtran.database.provider và OK

– Lúc này trong cửa sổ Project

Tạo các lớp Content Provider

– Sau khi tạo gói com.ngocminhtran.database.provider, chúng ta sẽ thêm các lớp đến gói này bằng cách chọn và nhấn chuột phải vào tên gói (com.ngocminhtran.database.provider) chọn New > Other > Content Provider

– Trong hộp thoại Configure Component chọn chấp nhận tên mặc định của lớp là MyContentProvider và nhập com.ngocminhtran.database.provider.MyContentProvider trong URI Authorities:

Giữ nguyên các tùy chọn khác và nhấn Finish. Lúc này, lớp MyContentProvider.java sẽ xuất hiện trong gói com.ngocminhtran.database.provider

Và chúng ta có thể xem nội dung mặc định của tập tin này bằng cách nhấn đôi chuột trái

Tạo Authority URI và Content URI

Trong tập tin MyContentProvider.java thêm các đoạn mã sau:

package com.ngocminhtran.database.provider; import android.content.ContentProvider; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.content.UriMatcher; public class MyContentProvider extends ContentProvider { private static final String AUTHORITY ="com.ngocminhtran.database.provider.MyContentProvider"; private static final String STUDENTS_TABLE = "Students"; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + STUDENTS_TABLE); public MyContentProvider() { } ...

Chúng ta tạo chuỗi tên AUTHORITY chứa thông tin về Authority URI, chuỗi tên STUDENTS_TABLE chứa thông tin về bảng cơ sở dữ liệu (Students) và chuỗi tên CONTENT_URI là kết hợp của hai chuỗi AUTHORITY và STUDENTS_TABLE bắt đầu bằng chuỗi content:// dùng phương thức parse của lớp Uri.

Đối tượng UriMatcher

URI là một giải pháp cho phép xác định dữ liệu, có thể là một hàng hay một bảng cơ sở dữ liệu, với một Content Provider cụ thể. Chúng ta để ý các phương thức trong lớp MyContentProvider như insert(), delete(), getType(), v.v. đều nhận một URI làm tham số. URI này như một tham chiếu đến một bảng cơ sở dữ liệu hay một hàng cụ thể của bảng đó và trách nhiệm chúng ta là chuyển kiểu Uri phù hợp đến các phương thức. Nhiệm vụ này có thể thực hiện một cách dễ dàng nhờ đối tượng UriMatcher. Khi một thể hiện của UriMatcher được tạo, nó sẽ được cấu hình để trả về một số nguyên tương ứng với kiểu Uri mà nó được yêu cầu. Trong ứng dụng hiện tại, chúng ta sẽ cấu hình thể hiện UriMatcher trả về giá trị 1 nếu tham chiếu đến toàn bộ bảng cơ sở dữ liệu (ví dụ Students) và trả về giá trị 2 nếu tham chiếu đến ID của một hàng nào đó. Thêm hai biến số nguyên tương ứng với hai kiểu Uri vào lớp MyContentProvider như sau:

public class MyContentProvider extends ContentProvider { private static final String AUTHORITY ="com.ngocminhtran.database.provider.MyContentProvider"; private static final String STUDENTS_TABLE = "Students"; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + STUDENTS_TABLE); public static final int STUDENTS = 1; public static final int STUDENTS_ID = 2; public MyContentProvider() { } ...

Kế tiếp, tạo thể hiện UriMatcher và cấu hình nó trả về các giá trị số nguyên phù hợp:

public class MyContentProvider extends ContentProvider { private static final String AUTHORITY ="com.ngocminhtran.database.provider.MyContentProvider"; private static final String STUDENTS_TABLE = "Students"; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + STUDENTS_TABLE); public static final int STUDENTS = 1; public static final int STUDENTS_ID = 2; private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH); static { sURIMatcher.addURI(AUTHORITY, STUDENTS_TABLE, STUDENTS); sURIMatcher.addURI(AUTHORITY, STUDENTS_TABLE + "/#",STUDENTS_ID); } public MyContentProvider() { }

Thực thi phương thức onCreate()

Phương thức onCreate() sẽ được gọi khi lớp Content Provider được tạo. Mục đích gọi onCreate() trong ứng dụng minh họa này là tạo một thể hiện của lớp DataHandler (một bản sao của lớp DataHandler từ ứng dụng trong Phần 1). Để tạo thể hiện DataHandler và sử dụng các phương thức trong lớp này, chúng ta cần khai báo lớp DataHandler trong tập tin MyContentProvider.java và vì lớp DataHandler được chứa trong gói com.ngocminhtran.sqlitedemoapplication

nên chúng ta khai báo như sau:

package com.ngocminhtran.database.provider; import android.content.ContentProvider; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.content.UriMatcher; import com.ngocminhtran.sqlitedemoapplication.DataHandler; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; import android.text.TextUtils; public class MyContentProvider extends ContentProvider { ... }

Khởi tạo thể hiện lớp DataHandler trong phương thức onCreate() như sau:

public class MyContentProvider extends ContentProvider { ... private DataHandler myHandler; public MyContentProvider() { } @Override public boolean onCreate() { // TODO: Implement this to initialize your content provider on startup. myHandler = new DataHandler(getContext(), null, null, 1); return false; } ... }

Thực thi phương thức insert()

Khi một ứng dụng khách hay một activity yêu cầu thêm dữ liệu đến cơ sở dữ liệu, phương thức insert() của lớp Content Provider sẽ được gọi. Phương thức insert() mặc định trong tập tin MyContentProvider.java như sau:

@Override public Uri insert(Uri uri, ContentValues values) { // TODO: Implement this to handle requests to insert a new row. throw new UnsupportedOperationException("Not yet implemented"); }

Tham số của phương thức insert() là một Uri xác định cơ sở dữ liệu và một đối tượng ContentValues chứa giá trị cần thêm vào cơ sở dữ liệu đó. Bây giờ chúng ta sẽ thay đổi phương thức insert() thực hiện một số chức năng sau:

  • Dùng một đối tượng UriMatcher để xác định kiểu Uri. Trong minh họa của chúng ta là đối tượng sUriMatcher.
  • Phát sinh một ngoại lệ nếu Uri không hợp lệ.
  • Xác định một tham chiếu đến cơ sở dữ liệu cần thêm dữ liệu.
  • Thực thi lệnh truy vấn SQL để thêm dữ liệu đến cơ sở dữ liệu.
  • Thông báo khi cơ sở dữ liệu được thay đổi.
  • Trả về Uri của hàng vừa thêm.

Phương thức insert() lúc này sẽ trông như sau:

@Override public Uri insert(Uri uri, ContentValues values) { int uriType = sURIMatcher.match(uri); SQLiteDatabase sqlDB = myHandler.getWritableDatabase(); long id = 0; switch (uriType) { case STUDENTS: id = sqlDB.insert(DataHandler.TABLE_NAME,null, values); break; default: throw new IllegalArgumentException("Unknown URI: "+ uri); } getContext().getContentResolver().notifyChange(uri, null); return Uri.parse(STUDENTS_TABLE + "/" + id); }

Thực thi phương thức query()

Khi một content provider được gọi để trả về dữ liệu, phương thức query() của lớp Content Provider sẽ được gọi. Phương thức query() mặc định của tập tin MyContentProvider.java như sau:

@Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // TODO: Implement this to handle query requests from clients. throw new UnsupportedOperationException("Not yet implemented"); }

Khi được gọi, phương thức này sẽ chuyển một vài hay toàn bộ các đối số sau:

  • uri: xác định cơ sở dữ liệu cần truy vấn
  • projection: một hàng trong một bảng dữ liệu
  • selection: lệnh “where” được thực thi
  • selectionArgs: các tham số bổ sung cho thao tác truy vấn chọn
  • sortOrder: thứ tự cho các hàng được chọn

Phương thức query() sẽ thực hiện một số chức năng sau:

  • Dùng một đối tượng UriMatcher để xác định kiểu Uri. Trong minh họa của chúng ta là đối tượng sUriMatcher.
  • Phát sinh một ngoại lệ nếu Uri không hợp lệ.
  • Tạo một truy vấn SQL dựa trên các tham số của phương thức.
  • Thực thi lệnh truy vấn SQL đến cơ sở dữ liệu.
  • Thông báo khi cơ sở dữ liệu được thay đổi.
  • Trả về đối tượng Cursor chứa kết quả truy vấn.

Phương thức query() được thay đổi như sau:

@Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); queryBuilder.setTables(DataHandler.TABLE_NAME); int uriType = sURIMatcher.match(uri); switch (uriType) { case STUDENTS_ID: queryBuilder.appendWhere(DataHandler.COLUMN_ID + "=" + uri.getLastPathSegment()); break; case STUDENTS: break; default: throw new IllegalArgumentException("Unknown URI"); } Cursor cursor = queryBuilder.query(myHandler.getReadableDatabase(),projection, selection, selectionArgs, null, null, sortOrder); cursor.setNotificationUri(getContext().getContentResolver(), uri); return cursor; }

Thực thi phương thức update()

Khi một content provider được gọi để thay đổi đến các hàng dữ liệu tồn tại trong bảng của sơ sở dữ liệu, phương thức update() của lớp Content Provider sẽ được gọi. Phương thức update() mặc định của tập tin MyContentProvider.java như sau:

@Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // TODO: Implement this to handle requests to update one or more rows. throw new UnsupportedOperationException("Not yet implemented"); }

Tham số của phương thức update() (tương tự phương thức query()):

  • uri: xác định cơ sở dữ liệu cần truy vấn
  • projection: một hàng trong một bảng dữ liệu
  • selection: lệnh “where” được thực thi
  • selectionArgs: các tham số bổ sung cho thao tác truy vấn chọn
  • sortOrder: thứ tự cho các hàng được chọn

Phương thức update() sẽ thực hiện một số chức năng sau:

  • Dùng một đối tượng UriMatcher để xác định kiểu Uri. Trong minh họa của chúng ta là đối tượng sUriMatcher.
  • Phát sinh một ngoại lệ nếu Uri không hợp lệ.
  • Xác định một tham chiếu đến cơ sở dữ liệu cần thay đổi dữ liệu.
  • Thực thi lệnh truy vấn SQL để cập nhật dữ liệu đến cơ sở dữ liệu.
  • Thông báo khi cơ sở dữ liệu được thay đổi.
  • Trả về số hàng đã được cập nhật.

Phương thức update() được thay đổi như sau:

@Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int uriType = sURIMatcher.match(uri); SQLiteDatabase sqlDB = myHandler.getWritableDatabase(); int rowsUpdated = 0; switch (uriType) { case STUDENTS: rowsUpdated = sqlDB.update(DataHandler.TABLE_NAME,values, selection, selectionArgs); break; case STUDENTS_ID: String id = uri.getLastPathSegment(); if (TextUtils.isEmpty(selection)) { rowsUpdated = sqlDB.update(DataHandler.TABLE_NAME, values, DataHandler.COLUMN_ID + "=" + id, null); } else { rowsUpdated = sqlDB.update(DataHandler.TABLE_NAME, values, DataHandler.COLUMN_ID + "=" + id + " and " + selection, selectionArgs); } break; default: throw new IllegalArgumentException("Unknown URI: " + uri); } getContext().getContentResolver().notifyChange(uri, null); return rowsUpdated; }

Thực thi phương thức delete()

Phương thức delete() được gọi khi cần xóa dữ liệu từ một cơ sở dữ liệu. Mặc định, phương thức delete() trong tập tin MyContentProvider.java sẽ như sau:

@Override public int delete(Uri uri, String selection, String[] selectionArgs) { // Implement this to handle requests to delete one or more rows. throw new UnsupportedOperationException("Not yet implemented"); }

Các đối số uri, selection, và selectionArgs có ý nghĩa tương tự hai phương thức query() và update(). Phương thức delete() thực hiện một số nhiệm vụ sau:

  • Dùng một đối tượng UriMatcher để xác định kiểu Uri. Trong minh họa của chúng ta là đối tượng sUriMatcher.
  • Phát sinh một ngoại lệ nếu Uri không hợp lệ.
  • Xác định một tham chiếu đến cơ sở dữ liệu cần xóa dữ liệu.
  • Thực thi lệnh truy vấn SQL để xóa dữ liệu trong cơ sở dữ liệu.
  • Thông báo khi cơ sở dữ liệu được thay đổi.
  • Trả về số hàng đã được cập nhật.

Phương thức delete() sẽ thay đổi như sau:

@Override public int delete(Uri uri, String selection, String[] selectionArgs) { int uriType = sURIMatcher.match(uri); SQLiteDatabase sqlDB = myHandler.getWritableDatabase(); int rowsDeleted = 0; switch (uriType) { case STUDENTS: rowsDeleted = sqlDB.delete(DataHandler.TABLE_NAME, selection, selectionArgs); break; case STUDENTS_ID: String id = uri.getLastPathSegment(); if (TextUtils.isEmpty(selection)) { rowsDeleted = sqlDB.delete(DataHandler.TABLE_NAME, myHandler.COLUMN_ID + "=" + id,null); } else { rowsDeleted = sqlDB.delete(DataHandler.TABLE_NAME, myHandler.COLUMN_ID + "=" + id + " and " + selection, selectionArgs); } break; default: throw new IllegalArgumentException("Unknown URI: " + uri); } getContext().getContentResolver().notifyChange(uri, null); return rowsDeleted; }

Khai báo Content Provider trong tập tin Manifest

Content Provider muốn được dùng trong một ứng dụng, nó cần phải được khai báo trong tập tin Manifest của ứng dụng đó. Khai báo Content Provider trong ứng dụng của chúng ta trong tập tin Manifest bằng cách vào app > manifests > AndroidManifest.xml và khai báo:

<application ...> <provider android:name="com.ngocminhtran.database.provider.MyContentProvider" android:authorities="com.ngocminhtran.database.provider.MyContentProvider" android:enabled="true" android:exported="true"> </provider> <activity> ... </activity> </application>

Thay đổi lớp DataHandler

Khi một content provider được thực thi, chúng ta cần thay đổi các phương thức trong lớp DataHandler (tập tin DataHandler.java) để có thể dùng content provider thông qua đối tượng content resolver. Đầu tiên, chúng ta cần import các gói chứa lớp Content Provider và ContentResolver như sau:

import com.ngocminhtran.database.provider.MyContentProvider; import android.content.ContentResolver;

Kế tiếp, chúng ta cần tham chiếu đến đối tượng ContentResolver dùng phương thức getContentResolver() trong phương thức khởi tạo của lớp DataHandler:

public class DataHandler extends SQLiteOpenHelper { private ContentResolver myCR; // các biến mô tả cơ sở dữ liệu private static final int DATABASE_VERSION = 1; private static final String DATABASE_NAME = "StudentsDB.db"; public static final String TABLE_NAME = "Students"; public static final String COLUMN_ID = "StudentID"; public static final String COLUMN_NAME = "StudentName"; //phương thức khởi tạo public DataHandler(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { super(context, DATABASE_NAME, factory, DATABASE_VERSION); myCR = context.getContentResolver(); } …

Bây giờ, chúng ta sẽ thay đổi các phương thức addDataHandler, findFisrtDataHandler, findAllDataHandler, deleteDataHandler và updateDataHandler

//thêm dữ liệu đến bảng Students public void addDataHandler(Student student) { //tạo đối tượng ContentValues ContentValues values = new ContentValues(); //thêm giá trị các cột đến đối tượng ContentValues values.put(COLUMN_ID, student.getStudentID()); values.put(COLUMN_NAME, student.getStudentName()); myCR.insert(MyContentProvider.CONTENT_URI, values); } //tìm kiếm Student theo StudentName //kết quả trả về là Student đầu tiên trong danh sách kết quả public Student findFisrtDataHandler(String studentname) { String[] projection = {COLUMN_ID, COLUMN_NAME }; String selection = "studentname = \"" + studentname +"\""; Cursor cursor = myCR.query(MyContentProvider.CONTENT_URI, projection, selection, null,null); Student student = new Student(); //trả về hàng đầu tiên trong kết quả if (cursor.moveToFirst()) { cursor.moveToFirst(); student.setStudentID(Integer.parseInt(cursor.getString(0))); student.setStudentName(cursor.getString(1)); cursor.close(); } else { student = null; } //trả về sinh viên đầu tiên tìm được return student; } //tìm kiếm Student theo StudentName //kết quả trả về là tất cả Student trong danh sách kết quả public List<Student> findAllDataHandler(String studentname) { String[] projection = {COLUMN_ID, COLUMN_NAME }; String selection = "studentname = \"" + studentname +"\""; // Thực thi truy vấn và gán kết quả đến đối tượng Cursor Cursor cursor = myCR.query(MyContentProvider.CONTENT_URI, projection, selection, null,null); //danh sách chứa tất cả các Student tìm được List<Student> lst =  new ArrayList<Student>(); //duyệt qua tất cả các hàng từ hàng đầu tiên if(cursor.moveToFirst()) { do { Student student = new Student(); student.setStudentID(Integer.parseInt(cursor.getString(0))); student.setStudentName(cursor.getString(1)); lst.add(student); }while (cursor.moveToNext()); } //đóng các đối tượng cursor.close(); //trả về danh sách sinh viên tìm được return lst; } public boolean deleteDataHandler(int ID) { boolean result = false; String selection = "studentid = \"" + ID +"\""; int rowsDeleted = myCR.delete(MyContentProvider.CONTENT_URI,selection, null); if (rowsDeleted > 0) result = true; return result; } public boolean updateDataHandler(int ID, String name) { ContentValues args = new ContentValues(); args.put(COLUMN_ID, ID); args.put(COLUMN_NAME, name); boolean result = false; String selection = "studentid = \"" + ID + "\""; int rowsUpdated = myCR.update(MyContentProvider.CONTENT_URI,args,selection,null); if (rowsUpdated > 0) result = true; return result; }

Đến lúc này chúng ta có thể kiểm tra ứng dụng với các chức năng Add, Find, Delete hay Update tương tự trong phần 1. Điểm khác biệt là chúng ta dùng đối tượng content provider được khai báo trong tập tin manifest. Với đối tượng content provider, các ứng dụng khác có thể truy cập dữ liệu dễ dàng hơn.

Mã nguồn của các tập tin trong ứng dụng có thể xem tại GitHub.

Học Lập trình Android trong Android Studio 3.X

Video liên quan

Chủ đề