1. 程式人生 > >四大組件初始之ContentProvider

四大組件初始之ContentProvider

增刪改 helper cts prot log mco lose pen roc

在android中,除了存放在外部存儲的共享目錄下的數據,各個應用的數據庫文件,資源等都是私有的,其他應用沒有訪問權限。所以有了ContentProvider,不包含功能邏輯,用於不同應用進程間共享數據,是數據訪問的接口。

一、工作流程

為了快速熟悉ContentProvider的工作流程。先創建一個沒有具體實現的ContentProvider。

1、創建ContentProvider

只要繼承android提供的ContentProvider並實現抽象方法即可。

import android.content.ContentProvider;

import android.content.ContentValues;

import android.database.Cursor;

import android.net.Uri;

import android.os.Process;

import android.util.Log;

 

public class MyContentProvider extends ContentProvider {

    private final static String Tag="ContentProvider";

    public MyContentProvider() {

    }

 

    @Override

    public int delete(Uri uri, String selection, String[] selectionArgs) {

        Log.d(Tag,"................delete");

        return 0;

    }

 

    @Override

    public String getType(Uri uri) {

        return null;

    }

 

    @Override

    public Uri insert(Uri uri, ContentValues values) {

        Log.d(Tag,".................insert");

        return null;

    }

 

    @Override

    public boolean onCreate() {

        Log.d(Tag,"..................onCreate,PID="+ Process.myPid());

        return false;

    }

 

    @Override

    public Cursor query(Uri uri, String[] projection, String selection,

                        String[] selectionArgs, String sortOrder) {

        Log.d(Tag,".................query");

        return null;

    }

 

    @Override

    public int update(Uri uri, ContentValues values, String selection,

                      String[] selectionArgs) {

      Log.d(Tag,"...................update");

        return 0;

    }

}

  

2、註冊

應用的組件都要在清單文件裏面註冊。

技術分享圖片

為了說明ContentProvider工作在不同的進程間,使用process屬性。

3、訪問

使用URI定位一個ContentProvide,URI值為註冊時的authorities屬性。

import android.content.ContentResolver;

import android.net.Uri;

import android.os.Process;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.util.Log;

 

public class MainActivity extends AppCompatActivity {

    private final static String Tag="MainActivity";

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        Log.d(Tag,"..............onCreate PID="+ Process.myPid());

        Uri uri=Uri.parse("content://org.su.example.contentper");

        ContentResolver contentResolver=getContentResolver();

        contentResolver.query(uri,null,null,null,null);

        contentResolver.query(uri,null,null,null,null);

        contentResolver.delete(uri,null,null);

        contentResolver.delete(uri,null,null);

    }

}

  

ContentResolver是android提供訪問ContentProvide的類。

日誌輸出

技術分享圖片

技術分享圖片

二、數據形式

ContentProvide的接口看起來就像數據庫的操作,增刪改查。ContentProvide的數據形式也多是組織成表格的形式。每個表有多列。表的一行代表一個記錄。這就意味著我們要使用一個ContentProvide還要知道它有哪些表,表結構是什麽樣的。一般android提供的ContentProvide都有一個說明類。例如訪問android的圖片的表結構可以通過MediaStore.Images獲得,聯系人信息通過ContactsContract.Contacts獲得。

三、自定義完整的ContentProvider

很多文章的表結構用的是book(id,name,author);

使用SQLiteOpenHelper

import android.content.Context;

import android.database.sqlite.SQLiteDatabase;

import android.database.sqlite.SQLiteOpenHelper;

 

public class DbOpenHelper extends SQLiteOpenHelper {

    private static final String DB_NAME = "book.db";

    public static final String TABLE_NAME = "book";

    private static final int DB_VERSION = 1;

    // book表

    private String CREATE_BOOK_TABLE = "CREATE TABLE IF NOT EXISTS "

            + TABLE_NAME + "(_id INTEGER PRIMARY KEY," + "name TEXT,"+" author TEXT)";

 

    public DbOpenHelper(Context context) {

        super(context,DB_NAME,null,DB_VERSION);

    }

    @Override

    public void onCreate(SQLiteDatabase db) {

        db.execSQL(CREATE_BOOK_TABLE);

    }

    @Override

    public void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion){

        // TODO ignored

    }

}

  

BookProvider代碼

import android.content.ContentProvider;

import android.content.ContentValues;

import android.content.Context;

import android.database.Cursor;

import android.database.sqlite.SQLiteDatabase;

import android.net.Uri;

import android.util.Log;

 

public class BookProvider extends ContentProvider {

    private static final String TAG = "BookProvider";

    public static final String AUTHORITY = "org.su.book.provider";

    public static final Uri URI = Uri.parse("content://"

            + AUTHORITY + "/book");

    private Context mContext;

    private SQLiteDatabase mDb;

 

    @Override

    public boolean onCreate() {

        Log.d(TAG,"onCreate,current thread:"+ Thread.currentThread().getName());

        mContext = getContext();

        //初始化數據

        initProviderData();

        return true;

    }

    private void initProviderData() {

        mDb = new DbOpenHelper(mContext).getWritableDatabase();

        mDb.execSQL("delete from " + DbOpenHelper.TABLE_NAME);

        mDb.execSQL("insert into book values(3,‘Android‘,‘Android‘);");

        mDb.execSQL("insert into book values(4,‘Ios‘,‘Ios‘);");

        mDb.execSQL("insert into book values(5,‘Html5‘,‘web‘);");

    }

 

    @Override

    public Cursor query(Uri uri,String[] projection,String selection,

                        String[] selectionArgs,String sortOrder) {

        String table = getTableName(uri);

        if (table == null) {

            throw new IllegalArgumentException("Unsupported URI: " + uri);

        }

        return mDb.query(table,projection,selection,selectionArgs,null,

                null,sortOrder,null);

    }

    @Override

    public String getType(Uri uri) {

        Log.d(TAG,"getType");

        return null;

    }

    @Override

    public Uri insert(Uri uri,ContentValues values) {

        Log.d(TAG,"insert");

        String table = getTableName(uri);

        if (table == null) {

            throw new IllegalArgumentException("Unsupported URI: " + uri);

        }mDb.insert(table,null,values);

        mContext.getContentResolver().notifyChange(uri,null);

        return uri;

    }

    @Override

    public int delete(Uri uri,String selection,String[] selectionArgs) {

        Log.d(TAG,"delete");

        String table = getTableName(uri);

        if (table == null) {

            throw new IllegalArgumentException("Unsupported URI: " + uri);

        }

        int count = mDb.delete(table,selection,selectionArgs);

        if (count > 0) {

            getContext().getContentResolver().notifyChange(uri,null);

        }

        return count;

    }

    @Override

    public int update(Uri uri,ContentValues values,String selection,

                      String[] selectionArgs) {Log.d(TAG,"update");

        String table = getTableName(uri);

        if (table == null) {

            throw new IllegalArgumentException("Unsupported URI: " + uri);

        }

        int row = mDb.update(table,values,selection,selectionArgs);

        if (row > 0) {

            getContext().getContentResolver().notifyChange(uri,null);

        }

        return row;

    }

    private String getTableName(Uri uri) {

        String tableName = null;

        if(uri.equals(URI))

            tableName=DbOpenHelper.TABLE_NAME;

        return tableName;

    }

}

  

在MainActivity中訪問

Uri uri=Uri.parse("content://org.su.book.provider/book");

        ContentResolver contentResolver=getContentResolver();

        ContentValues values = new ContentValues();

        values.put("_id",6);

        values.put("name","程序設計");

        values.put("author","c");

        contentResolver.insert(uri,values);

        Cursor bookCursor =contentResolver.query(uri,new String[]

                {"_id","name","author"},null,null,null);

        while (bookCursor.moveToNext()) {

            int id= bookCursor.getInt(0);

            String name = bookCursor.getString(1);

            String author =bookCursor.getString(2);

            Log.d(Tag,"query book:" +"id ="+id+",name ="+name+",author ="+author);

        }

        bookCursor.close();

  

日誌輸出:

技術分享圖片

四大組件初始之ContentProvider