首先解釋為什么需要模塊開發(fā)。在大型的Android項目中有很多組是單獨開發(fā)自己的模塊的。比如有商業(yè)化組,UGC組等等。但是有時候可能我想從商業(yè)化的A中去調(diào)用或者跳轉(zhuǎn)到UGC的B中。這時候為了不破壞整體項目結(jié)構(gòu),就需要本文所提的這個東西。情況如下圖所示,就好像網(wǎng)絡(luò)中的路由表一樣。所以最終目的就是維護一個路由表來使得各個Module之間相互聯(lián)系。
屏幕快照 2017-06-03 下午8.45.01.png
屏幕快照 2017-06-03 下午8.45.10.png
首先看看我們最后實現(xiàn)路由后的使用發(fā)方式:首先在Application中注冊路由
然后在各自的地方使用。
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
setupRouter();
}
private void setupRouter() {
Router.addRouter(ActivityRule.ACTIVIVY_SCHEME + "a_activity", AActivity.class);
Router.addRouter(ActivityRule.ACTIVIVY_SCHEME + "b_activity", BActivity.class);
}
}
使用事例
public class AActivity extends AppCompatActivity {
Button button;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.aactivity_layout);
button = (Button) findViewById(R.id.go_to_B);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = Router.invoke(AActivity.this, ActivityRule.ACTIVIVY_SCHEME+"b_activity");
startActivity(intent);
}
});
}
}
首先創(chuàng)建一個Rule接口
public interface Rule<T, V> {
/**
* 添加具體的路由
* @param pattern
* @param klass
*/
void router(String pattern, Class<T> klass);
/**
* 添加實現(xiàn) 例如Intent
* @param pattern
*/
V invoke(Context ctx, String pattern);
}
創(chuàng)建具體的實現(xiàn)類
public abstract class BaseRule<T> implements Rule<T, Intent> {
//Intent路由表
private HashMap<String, Class<T>> mRules = new HashMap<>();
@Override
public void router(String pattern, Class<T> klass) {
mRules.put(pattern, klass);
}
/**
* 構(gòu)造一個Intent
* @param ctx
* @param pattern
* @return
*/
@Override
public Intent invoke(Context ctx, String pattern) {
Class<T> klass = mRules.get(pattern);
if (klass == null) {
throwsException(pattern);
}
return new Intent(ctx, klass);
}
public abstract void throwsException(String pattern);
}
創(chuàng)建一個具體的Rule類比如ActivityRule類
public class ActivityRule<Activity> extends BaseRule<Activity> {
public static final String ACTIVIVY_SCHEME = "activity_route";
@Override
public void throwsException(String pattern) {
throw new ActivityNotFoundException(pattern);
}
}
在創(chuàng)建好各個Rule對象后,我們在創(chuàng)建一個Router的代理類RouterInternal
package com.example.mylibrary.router;
import android.content.Context;
import java.util.HashMap;
import java.util.Set;
/**
* Created by fupeidong on 2017/6/3.
*/
public class RouterInternal {
private static RouterInternal sInstance;
/** scheme->路由規(guī)則 */
private HashMap<String, Rule> mRules;
private RouterInternal() {
mRules = new HashMap<>();
initDefaultRouter();
}
/**
* 可以擴展比如Service和Broadcast等
*/
private void initDefaultRouter() {
addRule(ActivityRule.ACTIVIVY_SCHEME, new ActivityRule());
}
static RouterInternal get() {
if (sInstance == null) {
synchronized (RouterInternal.class) {
if (sInstance == null) {
sInstance = new RouterInternal();
}
}
}
return sInstance;
}
public final RouterInternal addRule(String scheme, Rule rule) {
mRules.put(scheme, rule);
return this;
}
private <T,V> Rule<T,V> getRule(String pattern) {
HashMap<String, Rule> rules = mRules;
Set<String> keySet = rules.keySet();
Rule<T,V> rule = null;
for (String scheme: keySet) {
if (pattern.startsWith(scheme)) {
rule = rules.get(scheme);
break;
}
}
return rule;
}
public final <T> RouterInternal addRouter(String pattern, Class<T> klass) {
Rule<T, ?> rule = getRule(pattern);
if (rule == null) {
throw new NotRouteException("unknown" + pattern);
}
rule.router(pattern, klass);
return this;
}
final <V> V invoke(Context ctx, String pattern) {
Rule<?, V> rule = getRule(pattern);
if (rule == null) {
throw new NotRouteException("unknown"+pattern);
}
return rule.invoke(ctx, pattern);
}
}
最后我們創(chuàng)建我們的使用類Router
public class Router {
public static RouterInternal addRule(String scheme, Rule rule) {
RouterInternal routerInternal = RouterInternal.get();
routerInternal.addRule(scheme, rule);
return routerInternal;
}
public static <T> RouterInternal addRouter(String pattern, Class<T> klass) {
return RouterInternal.get().addRouter(pattern, klass);
}
public static <V> V invoke(Context ctx, String pattern) {
return RouterInternal.get().invoke(ctx, pattern);
}
}