android 四大組件之ContentProvider1.

1.從學習android到至今已經有一年的時間了,四大組件中用到了三個唯獨contentprovider沒有被用到過,而且對這個也不是很理解,但是學習《android開發藝術探究》之後在第二章的IPC機制中,提到一種方法就是contentprovider。通過contentprovider可以實現數據共享。

2.contentprovider暴露數據的接口,這樣其他的程序可以通過Uri來訪問這個contentprovider的數據。我們知道每個app運行的時候都佔用一個進程,contentprovider可以實現進程間的通訊。這個demo分爲倆部分,一個是提供contentprovider的應用的app,我們稱爲service,另外一個應用程序我們稱爲client,也就是說這次我們要寫倆個應用程序。


3.Service端。第一步首先要繼承contentprovider,代碼如下:

package com.example.lenovo.contentprovidertest;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.support.annotation.Nullable;

/**
 * Created by lenovo on 21/6/2016.
 */
public class MyContentProvider extends ContentProvider {

    SQLiteDatabase writedb;
    SQLiteDatabase readb;
    Database d;
    final static String uri="content://com.example.lenovo.contentprovidertest.MyContentProvider1";
    final  static UriMatcher matcher=new UriMatcher(UriMatcher.NO_MATCH);
    static {
        matcher.addURI(uri,"Login",1);
    }
    @Override
    public boolean onCreate() {
         d=new Database(getContext(),"Login",null,1);

        return false;
    }

    @Nullable
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {

        readb=d.getReadableDatabase();
        Cursor cursor= readb.rawQuery("select * from user ",null);
        return cursor;
    }

    @Nullable
    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Nullable
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        writedb=d.getWritableDatabase();
        writedb.insert("user",null,values);
        return uri;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }
}

下面有幾個需要注意的地方:

oncreate(),方法運行在主線程中,因此在這個方法中我們不能做耗時操作。

UriMatcher類的作用:就是將authorities 和具體訪問的資源綁定起來,並且設置一個code,當匹配成功就會返回這個code。

例如:www.baidu.sa.html     www.baidu就相當於我們這的authorities  sa.html 相當具體的資源。關於contentprovider的uri不懂的可以找找資料看看。這裏不細說

當你繼承Contentprovider的時候,會要求重寫一些方法,那些方法都需要我們自己來實現,在我貼的代碼中,我是通過Sqliteopenhelper來管理一個數據庫的。具體代碼如下:

package com.example.lenovo.contentprovidertest;

import android.content.Context;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 * Created by lenovo on 21/6/2016.
 */
class Database extends SQLiteOpenHelper{

    public  String table="create table if not exists user(_id integer primary key autoincrement,name varchar(20),password varchar(20))";
    public Database(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    public Database(Context context, String name, SQLiteDatabase.CursorFactory factory, int version, DatabaseErrorHandler errorHandler) {
        super(context, name, factory, version, errorHandler);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(table);
    }

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

    }
}

寫好了這個Sqlieopenhelper之後,我們就可以在contentprovider類中,在相應的方法中,調用數據庫相應的操作。例如在contentprovider方法裏面有insert方法 那麼,在哪個方法內部我們需要調用數據庫執行insert的sql語句。詳細代碼請看上面的內容。

之後MainActivity的運行界面如下:


將username和password,輸入內容之後,通過調用contentprovider的insert方法保存起來。通過上面代碼可知,在insert方法中,我其實也是調用表的數據庫的insert操作。


寫完後最後一步就是在Manifest.xml裏面配置provider的信息。代碼如下:

<provider
            android:authorities="com.example.lenovo.contentprovidertest.MyContentProvider1"
            android:name=".MyContentProvider"
            android:exported="true"
            />
注意:exported 這個屬性要設置爲true。true表示可以在不同的進程中調用,false表示不可以。默認情況爲false。

之後安裝這個程序   輸入 內容然後保存起來,每當保存成功後  會有一個Toast彈出來。



4.再建立一個客戶端來調用service裏面的contentprovider。MainActivity的代碼如下:

package com.example.lenovo.clientcontentprivider;

import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    final static String uri="content://com.example.lenovo.contentprovidertest.MyContentProvider1/Login";
    ContentResolver contentResolver;
    Button but;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        but= (Button) findViewById(R.id.query);
        but.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                contentResolver=getContentResolver();
                Cursor cursor=contentResolver.query(Uri.parse(uri), null, null, null, null);

                while (cursor.moveToNext())
                {
                    String s=cursor.getString(cursor.getColumnIndex("name"));
                   String s1= cursor.getString(cursor.getColumnIndex("password"));
                    Toast.makeText(MainActivity.this,s, Toast.LENGTH_SHORT).show();
                }
                cursor.close();
            }
        });
    }
}

通過contentResolver.query方法來查詢 Service應用保存的那些username,和password的數據。


總結:contentprovider這個類,主要是把一些需要跨進程調用的數據,保存到數據庫中,其他應用程序通過一個uri來訪問那個數據庫,進而查詢到數據。

這篇文章主要針對一些對contentprovider瞭解點的人,但是又不是很明白。最開始我也不是很懂contentprovider的使用,看視頻也不懂,覺得超級麻煩。但是現在看看覺得也不是那麼麻煩,掌握了邏輯,熟悉了過程,代碼只是其次。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章