Android——内容提供者

Android 基础中最重要的就四大组件,四大组件是Android学习的开始。
activity ——算作Android界面
service——服务
Broadcast Receiver——广播
Content Provider——内容提供者
这四大组件开始对我来说内容提供者是最难理解的,但是慢慢接触之后感觉也不是很难。相对于基础来说吧。
这两天我又看了这一章的内容,就在这做个笔记吧

内容提供者。就按字面意思来理解 Android手机的内容,提供出来的工具
在做黑马教程(手机卫士)的时候就要提取出联系人,短信等数据的时候就要到了内容提供者
它是不同应用程序直接进行数据交换的标准API,当一个应用程序需要把自己的数据暴露出来给其他应用使用的时候,该应用程序
就可以通过提供contentProvider来实现:其他应用程序就可以通过ContentResolver来操作ContentProvider暴露出来的数据(抄的疯狂Android)

这里就可以知道,Android的内容提供者是有两部分组成的,这样想。内容当做事一个苹果树,A是苹果树的拥有者,如果B想要就需要拿钱去买。
但是A想卖,B才能买。买卖交换就要有市场。
简单点说就是其他应用拿数据,需要一个桥梁这就出现了内容提供者
Uri就是这个桥梁
想利用好内容提供者就要知道Uri。
假设你想去百度获取信息,该怎么办。首先得去百度网站才能吧。那也就是去到百度的界面,去百度的网站 
同理,B应用要拿到A应用的网站就要去A的网站。只是在这里应该是打引号的网站,先这样理解吧

从其他地方扒了一点过来
Uri代表了要操作的数据,Uri主要包含了两部分信息
①需要操作的ContentProvider
②对ContentProvider中的什么数据进行操作
组成部分
①scheme:ContentProvider的scheme已经由Android所规定为content://
②主机名(Authority):用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。建议为公司域名,保持唯一性
③路径(path):可以用来表示我们要操作的数据,路径的构建应根据业务而定:

要操作person表中id为10的记录,可以构建这样的路径:/person/10
要操作person表中id为10的记录的name字段, person/10/name
要操作person表中的所有记录,可以构建这样的路径:/person
要操作xxx表中的记录,可以构建这样的路径:/xxx
当然要操作的数据不一定来自数据库,也可以是文件等他存储方式,如下:  
要操作xml文件中person节点下的name节点,可以构建这样的路径:/person/name
如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
Uri uri = Uri.parse("content://com.jbridge.provider.personprovider/person")

下面就直接写代码把。方法直接就在代码直接说

1
import android.content.ContentProvider;
2
import android.content.ContentValues;
3
import android.database.Cursor;
4
import android.net.Uri;
5
import android.support.annotation.NonNull;
6
import android.support.annotation.Nullable;
7
import android.util.Log;
8
9
/**
10
 * Created by YacaToy on 2017/6/24.
11
 */
12
//ContentProvider的创建和其他四大组件差不多,都要继承然后在清单文件中配置好
13
public class FirstProvider extends ContentProvider {
14
    private String Tag = "ContentProvider";
15
    //第一次创建该ContentProvider时调用该方法
16
    @Override
17
    public boolean onCreate() {
18
        Log.w(Tag, "onCreate: 第一次创建用该方法");
19
        return false;
20
    }
21
22
    @Nullable
23
    @Override
24
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
25
                        @Nullable String[] selectionArgs, @Nullable String sortOrder) {
26
        Log.w(Tag , "query: 调用");
27
        Log.w(Tag , "selection: 参数是"+selection);
28
        return null;
29
    }
30
31
    //该返回的返回值代表ContentProvider所提供的MIME类型
32
    @Nullable
33
    @Override
34
    public String getType(@NonNull Uri uri) {
35
        return null;
36
    }
37
38
    //实现插入的方法,该方法应该返回新插入的纪录的Uri
39
    @Nullable
40
    @Override
41
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
42
        Log.w(Tag , "insert: 调用");
43
        Log.w(Tag , "values: 参数是"+values);
44
        return null;
45
    }
46
47
    //实现删除方法,该方法应该返回被删除的纪录条数
48
    @Override
49
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
50
        Log.w(Tag , "delete: 调用");
51
        Log.w(Tag , "selection: 参数是"+selection);
52
        return 0;
53
    }
54
55
    //实现更新方法,该方法应该返回被更新的纪录条数
56
    @Override
57
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
58
        Log.w(Tag , "update: 不调用");
59
        Log.w(Tag , "selection: 参数是"+selection+"values"+values);
60
        return 0;
61
    }
62
}
清单文件
1
           <provider
2
            android:authorities="org.crazyit.providers.firstprovider"  <!--这么一长串的东西只是一个标识-->
3
            android:name=".content.FirstProvider"
4
            ></provider>
这个程序我就用了四个button,就没有添代码了
1
2
contentResolver = getContentResolver();
3
4
class MyOnClickListener implements View.OnClickListener {
5
6
        @Override
7
        public void onClick(View v) {
8
            switch (v.getId()){
9
                case R.id.query:  //查询
10
                        Cursor cursor = contentResolver.query(uri,null,"query_where",null,null);
11
                    Toast.makeText(getApplicationContext(),cursor+"",Toast.LENGTH_SHORT).show();
12
                    break;
13
                case R.id.insert: //插入
14
                    ContentValues values = new ContentValues();
15
                    values.put("name","Yaca");
16
                    Uri nuwUri = contentResolver.insert(uri,values);
17
                    Toast.makeText(getApplicationContext(),values+"",Toast.LENGTH_SHORT).show();
18
                    break;
19
                case R.id.update:  //更新
20
                    ContentValues valuess = new ContentValues();
21
                    valuess.put("name","Yaca");
22
                    contentResolver.update(uri,valuess,"update_where",null);
23
24
                    break;
25
                case R.id.delete:  //删除
26
                    /**
27
                    代码
28
                    **/
29
                    break;
30
31
            }
32
        }
33
    }
然后我点击了 插入 出现了 
参数是name=Yaca

大致就是这么一个节奏

1
    //实现插入的方法,该方法应该返回新插入的纪录的Uri
2
    @Nullable
3
    @Override
4
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
5
        Log.w(Tag , "insert: 调用");
6
        Log.w(Tag , "values: 参数是"+values);
7
        return null;
8
    }

1
 case R.id.insert: //插入
2
                    ContentValues values = new ContentValues();
3
                    values.put("name","Yaca");
4
                    Uri nuwUri = contentResolver.insert(uri,values);
5
                    Toast.makeText(getApplicationContext(),values+"",Toast.LENGTH_SHORT).show();
6
                    break;
把这两个代码放在一起看,就懂了。 数据的操作无法就是增删改查。contentProvider定义 增删改查的方法。contentResolver提供参数

创建ContentProvider的说明
通过上面的介绍可以看出,ContentProvide不像Activity存在复杂的生命周期,ContentProvider只有一个onCreate()生命周期方法——当其他应用通过ContentResolver第一次方法该ContentProvider时
onCreate()方法将会被调用,onCreate只会被调用一次:ContentProvider提供的query(),insert(),update(),delete()方法则由其他应用用过ContentResolve调用这些方法时传入
前面介绍的示例由于并未真正对数据进行操作,因此ContentProvider实际能处理的Uri,以及确定每个方法中Uri参数所操作的额数据,Android系统提供了 UriMatcher工具类

void addURI(String authority,String path,int code):该方法用于向UriMatcher对象注册Uri,其中authorty和path组合成一个Uri,而code则代表Uri对应标识码
int match(Uri uri) : 根据前面注册的Uri来判断指定Uri对应的标识码,如果找不到匹配的标识码,该方法将会返回 -1

例如,我们先通过如下代码来创建UriMatcher对象
1
UriMatcher mather = new UriMathcer(UriMathcer.NO_MATCh);
2
mathcer.addURI("org.crazyit.providers.firstprovider","words",1);
3
mathcer.addURI("org.crazyit.providers.firstprovider","word/#",2);
上面创建的UriMatcher对象注册了两个Uri,其中 org.crazyit.providers.firstprovider/words对应的识别码为1;
org.crazyit.providers.firstprovider/word#对应的标识码为2;#为通配符
这就意味着如下匹配结果:
1
mathcer.match(Uri.parse("content:// org.crazyit.providers.firstprovider/words "));
2
//返回标识码为1
3
mathcer.match(Uri.parse("content:// org.crazyit.providers.firstprovider/word/2 "));
4
//返回标识码为2
5
mathcer.match(Uri.parse("content:// org.crazyit.providers.firstprovider/word/10 "));
6
//返回标识码为2
至于到底需要为UriMatcher对象注册多少个uri,则取决于系统的业务逻辑
对于 "content:// org.crazyit.providers.firstprovider/words "这个Uri,它的资源部分为words,这种资源通常代表了访问所以数据项;对应
"content:// org.crazyit.providers.firstprovider/word/2"这个Uri。它的资源部分通常代表访问数据项,其中最后一个数值往往代表了该数据的ID
除此之外,Android还提供了ContentUris工具类,它是一个操作Uri字符串的工具类
提供了如下两个工具方法

withAPPendedld(Uri,id)用于为路径加上ID部分
1
Uri uri = Uri.parse("content:// org.crazyit.providers.firstprovider/words ");
2
Uri resultUri = ContentUris.withAppendedId(Uri,2);
3
//生成后的Uri为:"content:// org.crazyit.providers.firstprovider/word/2"
Parseld(uri):用于从指定Uri种解析出所包含的ID值
1
Uri uri = Uri.parse("content:// org.crazyit.providers.firstprovider/word/2 ");
2
long wordId = ContentUris.parseId(uri);  //获取的结果为2

接下来我就写一个例子:还是老路子,学生信息管理 
在A应用上创建一个数据库,然后在B应用上调用A应用的数据

开始创建A应用:代码如下
数据库类的代码
1
import android.content.Context;
2
import android.database.DatabaseErrorHandler;
3
import android.database.sqlite.SQLiteDatabase;
4
import android.database.sqlite.SQLiteOpenHelper;
5
import android.util.Log;
6
7
/**
8
 * Created by YacaToy on 2017/6/23.
9
 */
10
11
public class MySQLieOpenHeler extends SQLiteOpenHelper {
12
    private String Tag = "MySQLieOpenHeler";
13
    public MySQLieOpenHeler(Context context) {
14
        super(context, "student.db", null, 1);
15
    }
16
17
    @Override
18
    public void onCreate(SQLiteDatabase db) {
19
        Log.w(Tag,"创建了SQL");
20
        db.execSQL("create table student (_id integer  primary key autoincrement , " +
21
                "name varchar(50),phone varchar(20));");
22
    }
23
24
    @Override
25
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
26
27
    }
28
}
然后就是创建一下A应用的ContentProvider基础类

1
import android.content.ContentProvider;
2
import android.content.ContentValues;
3
import android.database.Cursor;
4
import android.database.sqlite.SQLiteDatabase;
5
import android.net.Uri;
6
import android.support.annotation.NonNull;
7
import android.support.annotation.Nullable;
8
9
/**
10
 * Created by YacaToy on 2017/6/24.
11
 */
12
13
public class MyContent extends ContentProvider {
14
    private MySQLieOpenHeler dbOpenHelper;
15
    public boolean onCreate() {
16
        return false;
17
    }
18
19
    //查询
20
    @Nullable
21
    @Override
22
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
23
        //这里一定要记得 new MySQLieOpenHeler(this.getContext()); 否则就是爆空指针异常
24
        if(dbOpenHelper == null){
25
            dbOpenHelper = new MySQLieOpenHeler(this.getContext());
26
        }
27
        SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
28
        return db.query("student",projection,selection,selectionArgs,null,null,sortOrder);
29
    }
30
31
    @Nullable
32
    @Override
33
    public String getType(@NonNull Uri uri) {
34
//这个暂时我也不怎么会用,也就是返回出一个类型,根据类型数据来操作内容,以后我学好点的时候再来单独写一个博客吧。不好意思
35
        return null;
36
    }
37
38
    //添加
39
    @Nullable
40
    @Override
41
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
42
        if(dbOpenHelper == null){
43
            dbOpenHelper = new MySQLieOpenHeler(this.getContext());
44
        }
45
        SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
46
        db.insert("student",null,values);
47
        db.close();
48
        return null;
49
    }
50
51
    //删除
52
    @Override
53
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
54
        if(dbOpenHelper == null){
55
            dbOpenHelper = new MySQLieOpenHeler(this.getContext());
56
        }
57
        SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
58
        db.delete("student",selection,selectionArgs);
59
        db.close();
60
        return 0;
61
    }
62
63
    //更新
64
    @Override
65
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
66
        if(dbOpenHelper == null){
67
            dbOpenHelper = new MySQLieOpenHeler(this.getContext());
68
        }
69
        SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
70
        db.update("student",values,selection,selectionArgs);
71
        return 0;
72
    }
73
}
74
基本就是把,ContentResolver要调用的参数直接给数据操作。db了。这样也就相当于一个桥梁。直接把参数给它就成

一定要记得配置清单文件
1
       <provider
2
            android:authorities="com.yacatot.data.student"
3
            android:name=".MyContent"
4
            android:exported="true"
5
            ></provider>
最后一开始创建的时候就配置好,等下忘记了

好了。A应有提供功能就写完了。该是B应用了

布局文件我就写了四个按钮,没有做其他处理。有点儿懒
直接说吧。看代码
1
2
import android.content.ContentResolver;
3
import android.content.ContentValues;
4
import android.database.Cursor;
5
import android.net.Uri;
6
import android.support.v7.app.AppCompatActivity;
7
import android.os.Bundle;
8
import android.util.Log;
9
import android.view.View;
10
import android.widget.Button;
11
12
import java.util.ArrayList;
13
import java.util.List;
14
15
public class MainActivity extends AppCompatActivity {
16
    private String TAG= "MainActivity";
17
    ContentResolver contentResolver;
18
    Uri uri = Uri.parse("content://com.yacatot.data.student/");    //地址
19
    @Override
20
    protected void onCreate(Bundle savedInstanceState) {
21
        super.onCreate(savedInstanceState);
22
        setContentView(R.layout.activity_main);
23
        contentResolver = getContentResolver();
24
        //添加
25
        Button insert = (Button) findViewById(R.id.bt_insert);
26
        insert.setOnClickListener(new View.OnClickListener() {
27
            @Override
28
            public void onClick(View v) {
29
                ContentValues values = new ContentValues();
30
                values.put("name","zhangsan");
31
                values.put("phone","123456");
32
                contentResolver.insert(uri,values);
33
34
            }
35
        });
36
        //删除
37
        Button delete = (Button) findViewById(R.id.bt_delete);
38
        delete.setOnClickListener(new View.OnClickListener() {
39
            @Override
40
            public void onClick(View v) {
41
42
                contentResolver.delete(uri,"name = ?", new String[] {"zhangsan"} );
43
44
            }
45
        });
46
47
        //更新
48
        Button update = (Button) findViewById(R.id.bt_update);
49
        update.setOnClickListener(new View.OnClickListener() {
50
            @Override
51
            public void onClick(View v) {
52
                ContentValues values = new ContentValues();
53
                values.put("name","lisi");
54
                contentResolver.update(uri,values,"name = ?" , new String[] {"zhangsan"});
55
56
            }
57
        });
58
59
        //查询
60
        Button inquire = (Button) findViewById(R.id.bt_inquire);
61
        inquire.setOnClickListener(new View.OnClickListener() {
62
            @Override
63
            public void onClick(View v) {
64
65
                Cursor query = contentResolver.query(uri, null, null, null, null);
66
                List<StudentInfo> list = new ArrayList<StudentInfo>();
67
                while (query.moveToNext()){
68
                    StudentInfo info = new StudentInfo();
69
                    String name = query.getString(1);
70
                    info.setName(name);
71
                    String phone = query.getString(2);
72
                    info.setPhone(phone);
73
                    list.add(info);
74
                }
75
                Log.w(TAG,list.get(0).getName());
76
                Log.w(TAG,list.get(0).getPhone());
77
            }
78
        });
79
    }
80
}
81
这里说一下。查询。在A应有中
1
//查询
2
    @Nullable
3
    @Override
4
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
5
        //这里一定要记得 new MySQLieOpenHeler(this.getContext()); 否则就是爆空指针异常
6
        if(dbOpenHelper == null){
7
            dbOpenHelper = new MySQLieOpenHeler(this.getContext());
8
        }
9
        SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
10
        return db.query("student",projection,selection,selectionArgs,null,null,sortOrder);
11
    }
12
//这里返回的是Cursor类型,记得。Content只是一个桥梁,他不做好人好事。
13
内容提供者的基础就介绍完了。有什么问题一起讨论。新手之间多多学习














 


 
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值