模塊化是基于BaseLibrary開發(fā),日常開發(fā)是個(gè)app,打包時(shí)是個(gè)Library;這樣便于日常開發(fā)時(shí)編譯快,且可以快速把模塊化放入其它apk扯饶;限制就是只能有主App向各種業(yè)務(wù)模塊Library跳轉(zhuǎn),這也是為什么模塊化的前提详拙,需要在熟悉業(yè)務(wù)的情況模塊化帝际;如果各種頁面之間隨便跳也會(huì)讓模塊化失去意義
本篇需要的知識(shí)點(diǎn)是注解、動(dòng)態(tài)代理 饶辙、隱式跳轉(zhuǎn)等知識(shí)
1蹲诀、首先在BaseLibrary定義跳轉(zhuǎn)的路由注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface FullUrl {
String value();
}
2、在BaseLibrary定義跳轉(zhuǎn)的參數(shù)注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface IntentExtrasParam {
String value();
}
3弃揽、在BaseLibrary定義動(dòng)態(tài)代理
public class Router {
private Context context;
private static final String TAG = "Router";
public Router(Context context) {
this.context = context;
}
@SuppressWarnings("unchecked")
public <T> T create(Class<T> service){
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
StringBuilder builder = new StringBuilder();
FullUrl fullUrl = method.getAnnotation(FullUrl.class);
if(fullUrl instanceof FullUrl){
builder.append(fullUrl.value()).append("?");
}else {
throw new IllegalArgumentException("");
}
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
HashMap<String, Object> serializedParams = new HashMap<>();
for (int i=0;i<parameterAnnotations.length;i++){
Annotation[] parameterAnnotation = parameterAnnotations[i];
if (parameterAnnotation == null || parameterAnnotation.length == 0)
break;
Annotation annotation = parameterAnnotation[0];
if(annotation instanceof IntentExtrasParam){
IntentExtrasParam intentExtrasParam= (IntentExtrasParam) annotation;
serializedParams.put(intentExtrasParam.value(),args[i]);
}
}
performJump(builder.toString(),serializedParams);
return null;
}
});
}
private void performJump(String routerUri, HashMap<String, Object> serializedParams) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(routerUri));
Log.e(TAG, "performJump: "+ Uri.parse(routerUri));
Bundle bundle = new Bundle();
for (Map.Entry<String,Object> entry:serializedParams.entrySet()){
String key = entry.getKey();
Object value = entry.getValue();
//可以根據(jù)自己的項(xiàng)目需求自由擴(kuò)展支持?jǐn)?shù)據(jù)類型脯爪,這里只提供了String和Parcelable類型
if(value instanceof String){
bundle.putString(key,(String) value);
Log.e(TAG, "string: "+(String) value);
}else if(value instanceof Parcelable){
bundle.putParcelable(key, (Parcelable) value);
Log.e(TAG, "Parcelable: "+(Parcelable) value);
}else {
throw new IllegalArgumentException("不支持的數(shù)據(jù)類型");
}
}
intent.putExtras(bundle);
Log.e(TAG, "performJump: "+intent);
PackageManager packageManager = context.getPackageManager();
List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
if (!activities.isEmpty()) {
context.startActivity(intent);
}
}
}
4则北、在業(yè)務(wù)模塊的Library內(nèi)定義接口;需要注意的是,由App模塊跳轉(zhuǎn)到業(yè)務(wù)模塊的頁面定義的路由接口放到業(yè)務(wù)模塊內(nèi)痕慢,這樣便于管理業(yè)務(wù)模塊的路由頁面尚揣,這也是為什么不使用顯示跳轉(zhuǎn)或者隱式跳轉(zhuǎn)的原因,便于管理路由頁面
public interface RouterService {
@FullUrl("router://com.xiaoma.mylibrary.libraryactivity")
void startLibraryActivity(@IntentExtrasParam("stringParam") String stringParam,
@IntentExtrasParam("user") User user);
}
其中User類如下,其中g(shù)et/set相關(guān)方法和Parcelabel未寫出來
public class User implements Parcelable {
private String name;
private int age;
}
5掖举、業(yè)務(wù)模塊路由頁面的清單文件定義如下
<activity android:name="com.xiaoma.mylibrary.LibraryActivity">
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.VIEW" />
<data
android:host="com.xiaoma.mylibrary.libraryactivity"
android:scheme="router" />
</intent-filter>
</activity>
6快骗、在主App內(nèi),跳轉(zhuǎn)到模塊化頁面代碼
RouterService routerService = new Router(this).create(RouterService.class);
User user = new User("張三", 30);
routerService.startLibraryActivity("xiaoma", user);
7塔次、從主App跳轉(zhuǎn)到模塊化頁面獲取數(shù)據(jù)的代碼如下:
String stringParam = getIntent().getStringExtra("stringParam");
User user = getIntent().getParcelableExtra("user");