Android 之 ContentProvider学习
ContentProvider(内容提供者):
内容提供者主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访数据的安全性。目前,使用内容提供者是Android实现跨程序共享数据的标准方式。
内容提供者的用法一般有两种,一种是使用现有的内容提供者来读取和操作相应程序中的数据,另一种是创建自己的内容提供者给我们程序的数据提供外部访问接口。
这里我使用了上述两种用法中的第二种用法,也就是自己创建内容提供者的内容提供外部访问
话不多说,上代码
public class MyContentProvider extends ContentProvider {
@Override
public boolean onCreate() {
return false;
}
@Nullable
@Override
public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {
return null;
}
@Nullable
@Override
public String getType(Uri uri) {
return null;
}
@Nullable
@Override
public Uri insert(Uri uri, ContentValues contentValues) {
return null;
}
@Override
public int delete(Uri uri, String s, String[] strings) {
return 0;
}
@Override
public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
return 0;
}
}
这段代码是我自己写的一个类,继承于ContentProvider,同时重写了ContentProvider的6个方法。
可以看出,这里重写的6个方法里,包括了query,insert,update,delete4个基本操作
重写完这个类后,在AndroidManifest清单文件中进行配置
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.alei.myapplication">
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--配置内容提供者-->
<provider
android:authorities="com.alei.myapplication.WORKER"
android:name="com.alei.myapplication.MyContentProvider"
android:exported="true"/>
</application>
</manifest>
其中 provider 中的 name 指的是我们继承ContentProvider这个类的类名,而 authorities 则是指提供给外部的地址
配置完清单文件,然后开始写ContentProvider中的几个方法
这里的话,我就用query和delete测试了下
public class MyContentProvider extends ContentProvider {
private SQLiteDatabase db;
private UriMatcher uriMatcher;
@Override
public boolean onCreate() {
DBUtil dbUtil = new DBUtil(getContext(), "question.db", null, 1);
db = dbUtil.getWritableDatabase();
//实例化URI匹配器
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//添加规则
//01.查询所有
uriMatcher.addURI("com.alei.myapplication.WORKER","worker",1);
//02.查询单个
uriMatcher.addURI("com.alei.myapplication.WORKER","worker/#",2);
return false;
}
@Nullable
@Override
public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {
//根据URI匹配器开始匹配Uri
int code=uriMatcher.match(uri);
switch (code) {
case 1:
//查询所有
//获取数据库中所有的数据
return db.query(false,"worker",strings,s,strings1,null,null,s1,null);
case 2:
//查询单个
//获取# 的值
long id=ContentUris.parseId(uri);
return db.rawQuery("select * from worker where _id=?",new String[]{id+""});
}
return null;
}
@Nullable
@Override
public String getType(Uri uri) {
return null;
}
@Nullable
@Override
public Uri insert(Uri uri, ContentValues contentValues) {
return null;
}
@Override
public int delete(Uri uri, String s, String[] strings) {
long id=ContentUris.parseId(uri);
Log.i("test",id+"");
return db.delete("worker","_id=?",new String[]{id+""});
}
@Override
public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
return 0;
}
query方法中返回了查询出来的数据,上面代码中一个是查询所有的,一个是查询单个
为了方便看效果,我重新写了个Module用于测试上面代码的效果
这个是内容提供者,下面新Module数据来源
这个是新Module
下面这段是新Module的MainActivity 代码,同时也就写了这一个页面!
package com.alei.android_contentrelsolver;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private EditText et_main_queryText;
private ContentResolver cr;
private Uri uri;
private ListView lv_main_query;
private SimpleCursorAdapter adapter;
private Cursor cursor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获得内容访问者
cr = getContentResolver();
//初始化控件
et_main_queryText = (EditText) findViewById(R.id.et_main_queryText);
lv_main_query = (ListView) findViewById(R.id.lv_main_query);
}
/**
* 查询
*
* @param view
*/
public void queryData(View view) {
//判断文本框是否输入了条件
if (TextUtils.isEmpty(et_main_queryText.getText().toString())) {
//文本框为空
uri = Uri.parse("content://com.alei.myapplication.WORKER/worker");
} else {
//文本框有值
String id = et_main_queryText.getText().toString();
//这里使用Uri匹配器
uri = Uri.parse("content://com.alei.myapplication.WORKER/worker/" + id);
}
//将数据展示到listView
cursor = cr.query(uri, null, null, null, null);
adapter = new SimpleCursorAdapter(this, R.layout.item_list, cursor, new String[]{"_id", "name", "age"}, new int[]{R.id.tv_item_list_id, R.id.tv_item_list_name, R.id.tv_item_list_age});
lv_main_query.setAdapter(adapter);
//设置长按事件
lv_main_query.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
LinearLayout root = (LinearLayout) view;
String id = ((TextView) root.findViewById(R.id.tv_item_list_id)).getText().toString();
uri = Uri.parse("content://com.alei.myapplication.WORKER/worker/" + id);
//删除
cr.delete(uri, null, null);
query();
adapter.changeCursor(cursor);
return true;
}
});
}
public void query() {
uri = Uri.parse("content://com.alei.myapplication.WORKER/worker");
cursor = cr.query(uri, null, null, null, null);
}
}
至此,ContentProvider的一个轮廓也就差不多了,结果也能明显的看到,大功告成!