Android模块开发路由实现
2017-06-03 本文已影响0人
doufukobe
首先解释为什么需要模块开发。在大型的Android项目中有很多组是单独开发自己的模块的。比如有商业化组,UGC组等等。但是有时候可能我想从商业化的A中去调用或者跳转到UGC的B中。这时候为了不破坏整体项目结构,就需要本文所提的这个东西。情况如下图所示,就好像网络中的路由表一样。所以最终目的就是维护一个路由表来使得各个Module之间相互联系。
屏幕快照 2017-06-03 下午8.45.01.png屏幕快照 2017-06-03 下午8.45.10.png
首先看看我们最后实现路由后的使用发方式:首先在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);
}
});
}
}
首先创建一个Rule接口
public interface Rule<T, V> {
/**
* 添加具体的路由
* @param pattern
* @param klass
*/
void router(String pattern, Class<T> klass);
/**
* 添加实现 例如Intent
* @param pattern
*/
V invoke(Context ctx, String pattern);
}
创建具体的实现类
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);
}
/**
* 构造一个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);
}
创建一个具体的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);
}
}
在创建好各个Rule对象后,我们在创建一个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->路由规则 */
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);
}
}
最后我们创建我们的使用类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);
}
}