Android-ContentProvider流程

Android-ContentProvider原理及流程

Android为什么设计出一个ContentProvider ?

答:ContentProvider的出现主要是暴露数据出去,暴露什么数据呢 (暴露数据库SqliteDatabase里面的数据),由ContentProvider管控好增删改查,让其他应用程序来访问增删改查

  Android设计了intent-filter对外暴露(可以隐式意图激活/远程服务绑定通讯)这属于最组件的暴露,而ContentProvider属于数据库的暴露

  ContentProvider属于四大组件之一,Android把它设计成组件,说明ContentProvider是很重要的,Android操作系统源码APP几乎都大量用ContentProvider暴露了数据。

流程图:

注意:在ContentProvider里面写对数据库增删改查的时候,千万不能 db.close();  cursor.close(); 等操作,不然其他应用访问不到数据,也没有必要写isOpen();


ContentProviderServer应用

ContentProvider是抽象类,所以写一个类继承ContentProvider,重写增删改查系列方法

package liudeli.cp.server.cp;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;

public class MyContentProvider extends ContentProvider {

    private final String TAG = MyContentProvider.class.getSimpleName();

    /**
     * 只要在AndroidManifest.xml中配置了provider组件
     * 应用打开后,会自动启动此方法
     * @return
     */
    @Override
    public boolean onCreate() {
        Log.d(TAG, "onCreate()");
        return false;
    }

    /**
     * 查询
     * @param uri 其他应用传递过来的Uri
     * @param projection 其他应用传递过来的查询列
     * @param selection 其他应用传递过来的查询条件
     * @param selectionArgs 其他应用传递过来的查询条件参数值
     * @param sortOrder 其他应用传递过来的排序
     * @return
     */
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        Log.d(TAG, "查询到了数据....");
        return null;
    }

    /**
     * 增加
     * @param uri 其他应用传递过来的Uri
     * @param values  其他应用传递过来的ContentValues
     * @return
     */
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        Log.d(TAG, "插入了数据....");
        return null;
    }

    /**
     * 修改
     * @param uri 其他应用传递过来的Uri
     * @param values 其他应用传递过来的ContentValues
     * @param selection 其他应用传递过来的查询条件
     * @param selectionArgs 其他应用传递过来的查询条件参数值
     * @return
     */
    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        Log.d(TAG, "修改了数据....");
        return 0;
    }

    /**
     * 删除
     * @param uri 其他应用传递过来的Uri
     * @param selection 其他应用传递过来的查询条件
     * @param selectionArgs 其他应用传递过来的查询条件参数值
     * @return
     */
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        Log.d(TAG, "删除了数据....");
        return 0;
    }


    /**
     * 得到类型 在后续的博客中会有讲解到
     * @param uri
     * @return
     */
    @Override
    public String getType(Uri uri) {
        return null;
    }
}

在AndroidManifest.xml文件中,配置ContentProvider组件,然后对外暴露数据(设置授权唯一标识,允许对外输出,允许实例化激活)等操作

    <!--
            ContentProvider是组件需要配置
            可以把ContentProvider看作是服务器
            authorities 看作是服务器 服务器有访问的链接,authorities(授权) ,是唯一标识
            android:enabled="true" 可以被系统实例化
            android:exported="true" 允许对外输出
        -->
        <provider
            android:authorities="autho.prov.cp.MyContentProvider"
            android:name=".cp.MyContentProvider"
            android:enabled="true"
            android:exported="true"
            />

启动ContentProviderServer应用,注意看:一启动ContentProviderServer应用,就会自动初始化  MyContentProvider --> onCreate()方法

12-14 09:22:55.187 2013-2013/liudeli.cp.server D/MyContentProvider: onCreate()


ContentProviderClient应用

点击Test按钮,成功调用到 ContentProviderServer应用的 MyContentProvider -- > query() 方法

package liudeli.cp.client;

import android.content.ContentResolver;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void test(View view) {
        /**
         * 可以想象客户端访问服务器,需要需要用到协议HTTP
         * 而想访问ContentProvider,需要ContentResolver
         */
        ContentResolver contentProvider = getContentResolver();

        /**
         * 可以想象访问服务器,需要这样拼接访问地址 http://
         * 而想访问ContentProvider,需要这样拼接访问地址 content://
         * 必须拿到暴露的授权authorities="autho.prov.cp.MyContentProvider" 进行拼接
         */
        Uri uri = Uri.parse("content://autho.prov.cp.MyContentProvider");

        // 查询
        contentProvider.query(uri, null, null, null, null, null);

        // 增加
        // contentProvider.insert(uri, null);

        // 修改
        // contentProvider.update(uri, null, null, null);

        // 删除
        // contentProvider.delete(uri, null, null);
    }
}

ContentProviderServer应用的 MyContentProvider -- > query() 方法

12-14 09:44:59.955 2013-2031/liudeli.cp.server D/MyContentProvider: 查询到了数据....

原文地址:https://www.cnblogs.com/android-deli/p/10121028.html