ContentProvider的理解与使用

ContentProvider管理android以结构化方式存放的数据。

它以相对安全的方式封装数据并且提供简易的处理机制;
ContentProvider提供不同进程间数据交互的标准化接口;

1、ContentProvider简介、Uri简介、ContentResolver的简单使用;

ContentProvider:是允许不同应用进行数据交换的标准的API,ContentProvider以Uri的形式对外提供数据的访问操作接口,而其他应用则通过ContentResolver根据Uri去访问指定的数据;

一旦某个应用通过ContentProvider暴露了自己的数据接口,那么不管该应用程序是否启动,其他程序都可以通过该接口来操作自己的数据接口来操作其内部的数据,包括增加数据、删除数据、修改数据、查询数据等;

URI:是统一资源标识符,是一个用户标识某一互联网资源名称的字符串。该种标识允许用户对任何(包括本地和互联网)的资源通过特定的协议进行交互操作。URI由包括确定语法和相关协议的方案所定义。是由三个组成部分:
a:访问资源的命名机制;
b:存放资源的主机名;
c:资源自身的名称,由路径表示;
举个栗子
Content://com.android.seapp/s_xpp中:
Content://:使用的是content协议,属于默认规定;
com.android.seapp :属于自己定义的主机名,唯一标识并区分不同的ContentProvicer继承类;
s_xpp:资源部分,当访问不同的资源的时候,这部分会动态改变;

ContentProvider的使用离不开Uri类的支持,在自己的继承类中使用UriMatcher,根据UriMatcher.match(Uri uri)返回的表示符,进行不同范围,不同数据集的操作;
//自己继承类中的一个方法
@Override
public String getType(Uri uri){
    int code = matcher.match(uri);
    String type = null;
    if(code = ALL_APP){
        type = "vnd.adnroid.cursor.dir/s_xpp";//dir代表多行数据;
    }else if(code =2){
    type = "vnd.androd.cursor.item/s_xpp";//item单行;
    }
    return type;
}

一旦定义好自己的ContentProvider类,就可以使用ContentResolver进行访问操作了,ContentResolver类的方法都会在其内部调用URI主机部分确定的 ContentProvider

ContentResolver的内部方法的实现:

以ContentResolver.query(Uri uri,String[] projection,String selection,String[] selectionArgs,String sortOrder)为例;
 public final Cursor query(Uri uri, String[] projection,
            String selection, String[] selectionArgs, String sortOrder) {
        IContentProvider provider = acquireProvider(uri);
        if (provider == null) {
            return null;
        }
        try {
            long startTime = SystemClock.uptimeMillis();
            Cursor qCursor = provider.query(uri, projection, selection, selectionArgs, sortOrder);
            if (qCursor == null) {
                releaseProvider(provider);
                return null;
            }
            // force query execution
            qCursor.getCount();
            long durationMillis = SystemClock.uptimeMillis() - startTime;
            maybeLogQueryToEventLog(durationMillis, uri, projection, selection, sortOrder);
            // Wrap the cursor object into CursorWrapperInner object
            return new CursorWrapperInner(qCursor, provider);

可以发现,其内部检查了provider的存在,如果存在就调用该应用ContentProvider的query方法,说明ContentProvider实现了底层数据的增、删、查、改的功能

2、监听ContentProvider相关的数据变化(ContentObserver类)

使用ContentObserver可以监测某一数据项的变化,当其中的内容发生变化时会自动调用其中的public void onChange(boolean selfChange){}的方法;

package edu.android.demos.chap14;

import android.app.Activity;
import android.app.Service;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.provider.CallLog.Calls;
import android.util.Log;
import android.widget.TextView;
import edu.android.demos.R;

public class TestObserverActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(R.layout.chap14_observer);

        //创建内容handler,用于内容观察者向activity发送消息
        Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                StringBuilder s = (StringBuilder) msg.obj;
                ((TextView) findViewById(R.id.observer_show_sms)).setText(s
                        .toString());
            }
        };
        //注册内容观察者,监听短信数据变化
        getContentResolver().registerContentObserver(
                Uri.parse("content://sms"), true,
                new SMSObserver(handler, this));
    }
}

//实现内容观察者需要继承ContentObserver
class SMSObserver extends ContentObserver {
    Context context;
    Handler handler;

    public SMSObserver(Handler handler, Context context) {
        super(handler);
        this.handler = handler;
        this.context = context;
    }

    //当观察的内容发生变化是会触发该方法,内容发生变化是在该方法中做相应处理
    @Override
    public void onChange(boolean selfChange) {
        ContentResolver resolver = context.getContentResolver();
        Cursor c = resolver.query(Uri.parse("content://sms"), null, null, null,
                null);
        StringBuilder sb = new StringBuilder();
        while (c.moveToNext()) {
            sb.append("发件人手机号码: " + c.getString(c.getColumnIndex("address")))
                    .append("信息内容: " + c.getString(c.getColumnIndex("body")))
                    .append("是否查看: " + c.getString(c.getColumnIndex("read")))
                    .append("发送时间:"
                            + String.format("%tF %,
                                    c.getLong(c.getColumnIndex("date"))))
                    .append("\n");
        }
        Log.e("SMSObserver", sb.toString());
        Message msg = new Message();
        msg.obj = sb;//将读到的信息使用msg,传递给activity
        handler.sendMessage(msg);
    }
}

博客学习总结:摘录自“http://blog.csdn.net/u012858833/article/details/51629245”仅供自己浏览记录学习;

你可能感兴趣的:(测试,android)