上篇文章介绍了Serviceloader在组件间数据传递的应用,这次我们来看看ContentProvider怎样应用在组件化开发中。
我们知道,ContentProvider作为Android四大组件之一,常用来跨进程通信。只要我们设置ContentProvider的exported =true ,就可以对其他应用暴露自己的数据获取接口,利用这一特性,我们就可以将其利用在组件间的数据通信了。
如何使用?
首先我们假设一个应用场景,Module A 想要获取 Module B中的数据,同时它们都引用公共组件lib_common,用ContentProvider怎么做?
使用步骤:
1.在lib_common中定义一个通用数据获取接口, 用于上层数据传递:
public interface ProtocolApp {
void setCityId(int city_id);
void uploadLoginActive(String phoneNo);
//这里的数据获取方法自己定义
}
然后在lib_common中提供一个数据传递协议,用来对provider的获取:
public class Protocols {
public static ProtocolApp getProtocolApp(){
return (ProtocolApp) get("xxx.ProviderApp");//所在module中的provider定义的authorities字段
}
public static ContentProvider get(String authority){
ContentProviderClient client = getContext().getContentResolver().acquireContentProviderClient(authority);
if (client != null) {
return client.getLocalContentProvider();
}
return null;
}
private static Context context;
public static final Context getContext() {
if (context == null) {
try {
Method method = Class.forName("android.app.ActivityThread")
.getMethod("currentApplication");
method.setAccessible(true);
Application application = (Application) method.invoke(null, (Object[]) null);
if (application != null) {
context = application;
return application;
}
} catch (Exception e) {
e.printStackTrace();
}
try {
Method method = Class.forName("android.app.AppGlobals")
.getMethod("getInitialApplication");
method.setAccessible(true);
Application application = (Application) method.invoke(null, (Object[]) null);
if (application != null) {
context = application;
return application;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return context;
}
}
2.在module B的Mainifest.xml中定义provider:
<provider
android:authorities="xxx.ProviderApp"
android:name=".provider.ProviderApp"
android:exported="true"/> //这里必须为true
我们再来看看ProviderApp:
/**
* app组件对外提供的数据交换类
* Created by huolala-sunyan on 2018/8/10.
*/
public class ProviderApp extends ContentProvider implements ProtocolApp{
@Override
public boolean onCreate() {
return true;
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
return null;
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
return null;
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
return null;
}
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
@Override
public void setCityId(int city_id) {
MainApp.getInstance().city_id = city_id;
}
@Override
public void uploadLoginActive(String phoneNo) {
MainApp.getInstance().UploadloginActive(phoneNo);
}
}
这里我们只需要看我们在底层接口中定义的两个方法setCityId()跟upLoadLoginActive()方法,这两个方法就是通信的具体实现了。
3.最后我们在Module A中尝试跟Module B通信:
Protocols.getProtocolApp().uploadLoginActive(PhoneNo.getText().toString().trim());
可以看到,通过Protocols获取到Module B定义的provider,然后就可以调用其实现方法来进行通信了。
好了,ContentProvider在组件间通信就介绍到这儿了,下一篇我将介绍通过ARouter的IProvider来进行通信。