将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方法实现是否正确,这有待今后进一步深入学习。

Leave a comment

Your comment