将ContentProvider引入到Notepad Tutorial
Notepad Tutorial是一个了解Android和学习Android应用开发的很好的向导,通过这个向导,初学者可以快速领会Activity的基本用法,以及数据库的常规操作等。
但是因为这个向导是面向初学者的,因此在一些话题上,它没有做深入的探讨。例如如何通过ContentProvider来存取数据。细心的读者会在Exercise1中看到这样一行话:
If you wish for other activities to access or modify the data, you have to expose the data using a ContentProvider.
文档明确告诉了:如果要让其他activity操作数据,那么请使用ContentProvider。ContentProvider作为Android四个核心组件之一,我们没有理由回避它。由于Notepad Tutorial在数据读取中均是通过数据库操作直接完成,因此接下来的工作就是改变这种情形,使其通过ContentProvider来操作数据。
首先,增加一个ContentProvider的子类NotesProvider。完成之后,即可看到其一共有六个函数需要我们来实现。
增加一个内部类DatabaseHelper,–可以从NotesDbAdapter类中拷贝过来。
private static class DatabaseHelper extends SQLiteOpenHelper { DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table notes (_id integer primary key autoincrement, title text not null, body text not null);"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data"); db.execSQL("DROP TABLE IF EXISTS notes"); onCreate(db); } } |
由于Notepad Exercise1只是提供查询和增加两个功能,因此在这个ContentProvider中,暂时只简单实现onCreate()、insert()和query()三个方法。
private DatabaseHelper mDbHelper; private SQLiteDatabase mDb; @Override public boolean onCreate() { mDbHelper = new DatabaseHelper(getContext()); mDb = mDbHelper.getWritableDatabase(); return true; } @Override public Uri insert(Uri uri, ContentValues values) { long id = mDb.insert(DATABASE_TABLE, null, values); Uri u = Uri.withAppendedPath(uri, String.valueOf(id)); return u; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder(); qBuilder.setTables(DATABASE_TABLE); // make a query Cursor c = qBuilder.query(mDb, projection, selection, selectionArgs, null, null, sortOrder); c.setNotificationUri(getContext().getContentResolver(), uri); return c; } |
增加了ContentProvider,一定别忘了在AndroidManifest.xml里增加provider的节点:
<provider android:name="com.android.demo.notepad1.NotesProvider" android:authorities="com.android.demo.notepad1.notesprovider"> </provider> |
最后来修改Notepad1类,首先是onCreate方法,去掉对原来NotesDbAdapter类的使用。
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.notepad_list); fillData(); } |
然后来修改createNote和fillData两个方法:
private void createNote() { String noteName = "Note " + mNoteNumber++; ContentValues values = new ContentValues(); values.put(NotesProvider.KEY_BODY, ""); values.put(NotesProvider.KEY_TITLE, noteName); getContentResolver().insert(NotesProvider.CONTENT_URI, values); fillData(); } private void fillData() { // Get all of the notes from the database and create the item list String[] projection = new String[]{NotesProvider.KEY_ROWID, NotesProvider.KEY_TITLE, NotesProvider.KEY_BODY}; Cursor c = managedQuery(NotesProvider.CONTENT_URI, projection, null, null, null); startManagingCursor(c); String[] from = new String[] { NotesDbAdapter.KEY_TITLE }; int[] to = new int[] { R.id.text1 }; // Now create an array adapter and set it to display using our row SimpleCursorAdapter notes = new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to); setListAdapter(notes); } |
通过这个过程,简单熟悉了ContentProvider的自定义过程和ContentResolver的调用,美中不足的是,由于缺少参考资料,还不清楚BaseCollumns如何使用,以及ContentProvider的onCreate方法实现是否正确,这有待今后进一步深入学习。