您的位置:首页 > 编程语言 > PHP开发

ContentProvider、AsyncTaskLoader

2016-10-14 21:39 176 查看
IPC 进程间通信 在android中每个app都是独立的进程

ContentProvider

内容提供者

它是一个提供共享数据访问接口的应用程序组件

例如:通讯录这个app允许它的数据被其它的app访问 就可以通过ContentProvider暴露对外访问数据的方式

访问通话纪录

public class MainActivity extends AppCompatActivity {
private ListView lv;
private ContentResolver resolver;//内容观察者 解析者  获取ContentProvider暴露的数据
//    private String callLog="content://call_log/calls";  //字符串
private Uri callLogUri= CallLog.Calls.CONTENT_URI;//常量形式uri
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv= (ListView) findViewById(R.id.lv);
resolver=getContentResolver();//实例化
//调用ContentResolver中的query()方法查询contentprovider提供的数据
Cursor cursor=resolver.query(callLogUri,null,null,null,null);
SimpleCursorAdapter adapter=new SimpleCursorAdapter(this,R.layout.list_item,cursor,
new String[]{CallLog.Calls.NUMBER,CallLog.Calls.DATE,CallLog.Calls.TYPE},
//                                 new String[]{"number","date","type"}
new int[]{R.id.tv_number,R.id.tv_date,R.id.tv_type},
SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
lv.setAdapter(adapter);
}
}


如果app中需要将私有访问的数据共享给其它的app访问 就需要创建类继承ContentProvider 重写

相应的函数暴露数据访问的方式 增删改查

ContentProvider使用步骤:

1.创建类继承ContentProvider

2.重写相应的暴露数据访问接口的方法

3.注册ContentProvider

ContentProvider 服务端 需要共享数据的app

public class xx extends ContentProvider{

private static final UriMatcher matcher=new

UriMatcher(UriMatcher.NO_MATCH);

static{

matcher.adduri(String authority 自定义字符串 一般情况设置为包名,

String path 路径 自定义字符串 操作的表名 功能名称 * 表示匹配所有文本 # 表示匹配所有数字,

int code 表示client访问的uri地址与contentrovider提供的地址一致时返回的数字码);

…..

}

public Uri insert(Uri uri,ContentValues values){

if(matcher.match(uri)==数字码){

操作共享数据的插入

}

}

public Cursor query(Uri uri,String[] projection,String seletion,String[] seletionArgs,String sortOrder){

if(matcher.match(uri)==数字码){

操作共享数据的查询

}

}

public int update(Uri uri,ContentValues values,String seletion,String[] seletionArgs){

if(matcher.match(uri)==数字码){

操作共享数据的修改

}

}

public int delete(Uri uri,String seletion,String[] seletionArgs){

if(matcher.match(uri)==数字码){

操作共享数据的删除

}

}

}

全局清单文件中:

<application>
...
<provider
android:authorities="自定义字符串 matcher.adduri中的指定的权限一致即可"
android:name="当前住的contentrovider的包名.类名"
android:exported="true" 表示允许程序的数据被其它app访问/>
...
</applicaiton>


ContentResolver client客户端 专门访问ContentProvider暴露的数据

private ContentResolver resolver;

public class xxx extends Activity{

public void onCreate(Bundle…){

super.onCreate(..)

setContentView(R.layout.xxx);

resolver=getContentReslover();

Cursor cursor=resolver.query(xxxx);

resolver.insert(xxxx);

int count=resolver.update(xxxx);

int count2=resolver.delete(xxxxx);

}

}

AsyncTaskLoader:

Loader sdk3.0之后引入 异步加载数据

特点:使用Loader异步加载数据时 数据源发生改变时会直接将改变的数据展示到控件中 不需要重新查询

Loader可以在activity或者时fragment中使用

Loader 接口

AsyncTaskLoader 抽象类

CursorLoader主要适用场景:主要适合查询contentProvider提供的数据

使用步骤:

1.创建一个LoadManger对象

2.调用 initLoader()方法对loader进行初始化操作

public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor>{
private ListView lv;
private LoaderManager manager;
private MyCursorAdapter cursorAdapter;
private ContentResolver resolver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv= (ListView) findViewById(R.id.lv);
resolver=getContentResolver();
////实例化 LoadManger对象  每个Activity或者Fragment只能存在一个 LoaderManger对象
// 一个 LoadManger可以管理多个 Loader对象
manager=getLoaderManager();
/*
对Loader进行初始化
initLoader(int id, Bundle args,LoaderManager.LoaderCallbacks<D> callback)
如果不存在loader对象则直接创建 如果存在则复用最后创建的 Loader对象
int id, 表示唯一标示当前loader对象的id
Bundle args, 可选参数 表示传递到loader对象中的参数
LoaderManager.LoaderCallbacks<D> callback 回调接口 包括回调函数 针对loader不同状态会回调
范型 表示使用当前初始化的loader对象异步加载数据的类型
*/
Bundle bundle=new Bundle();
bundle.putString("key","annsngsgdofrgldghgfh");
manager.initLoader(1,bundle,this);

cursorAdapter=new MyCursorAdapter(this,null,CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
lv.setAdapter(cursorAdapter);
}

/**
* 表示创建loader对象时回调的函数
* @param id  初始化指定的loader的id标示
* @param args
* @return 创建完成的loader对象
*/
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
//new CursorLoader(上下文,使用cursorLoader异步加载contentProvider数据的uri地址,查询字段,
// 查询的条件,查询条件占位符,排序字段)
//之前使用ContentResolver访问provider提供数据现在变成使用cursorloader
CursorLoader loader=new CursorLoader(MainActivity.this, ContactsContract.Contacts.CONTENT_URI,
null,null,null,null);
Log.i("tag","-----onCreateLoader----"+args.getString("key"));
return loader;
}

/**
* 表示loader加载完毕数据时回调的函数
* @param loader 创建的loader
* @param data 表示通过loader对象加载获取的数据结果
*/
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
cursorAdapter.swapCursor(data);//将查询获取的cursor对象加载到适配器中
Log.i("tag","-----onLoadFinished----");
}

/**
* 表示loader重载或者是退出时回调的函数
* @param loader
*/
@Override
public void onLoaderReset(Loader<Cursor> loader) {
cursorAdapter.swapCursor(null);
Log.i("tag","-----onLoaderReset----");
}

public class MyCursorAdapter extends CursorAdapter{

public MyCursorAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(MainActivity.this).inflate(R.layout.list_item,null);
}

@Override
public void bindView(View view, Context context, Cursor cursor) {
TextView tv_id= (TextView) view.findViewById(R.id.tv_id);
TextView tv_displayName= (TextView) view.findViewById(R.id.tv_displayname);

tv_id.setText(cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts._ID))+"");
tv_displayName.setText(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)));
}
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main,menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.action_add://向系统通讯录应用中的 raw_contact表中插入联系人姓名和id
// content://con/person   insert  content://con/person/3
//向raw_contact表中插入一条空纪录 目的是为了得到raw_contact表中的自增的主键id
Uri newUri=resolver.insert(ContactsContract.RawContacts.CONTENT_URI,
new ContentValues());//content://con/person/3
long contactId= ContentUris.parseId(newUri);//3

//获取raw_contactId name mimtType   data表中插入
ContentValues values=new ContentValues();
values.put(ContactsContract.Data.RAW_CONTACT_ID,contactId);
values.put(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,"赵六赵六");
resolver.insert(ContactsContract.Data.CONTENT_URI,values);
break;
}
return super.onOptionsItemSelected(item);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android contentprovider