atom
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
package com.xiangxue.arouter_api;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
assertEquals("com.xiangxue.arouter_api.test", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
2
arouter_api/src/main/AndroidManifest.xml
Normal file
2
arouter_api/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,2 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.xiangxue.arouter_api" />
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.xiangxue.arouter_api;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Group分组的领头 带头大哥
|
||||
*
|
||||
*
|
||||
* TODO
|
||||
* * key: app
|
||||
* * value: ARouterPath
|
||||
*/
|
||||
public interface ARouterGroup {
|
||||
|
||||
/**
|
||||
* 例如:order分组下有这些信息,personal分组下有这些信息
|
||||
* 例如:"order" --- ARouterPath的实现类 -->(APT生成出来的 ARouter$$Path$$order)
|
||||
*
|
||||
* @return key:"order/app/personal" value:系列的order组下面所有的(path---class)
|
||||
*/
|
||||
Map<String, Class<? extends ARouterPath>> getGroupMap();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.xiangxue.arouter_api;
|
||||
|
||||
import com.xiangxue.arouter_annotation.bean.RouterBean;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 其实就是 路由组 Group 对应的 ---- 详细Path加载数据接口 ARouterPath
|
||||
* 例如:order分组 对应 ---- 有那些类需要加载(Order_MainActivity Order_MainActivity2 ...)
|
||||
*
|
||||
*
|
||||
* TODO
|
||||
* key: /app/MainActivity1
|
||||
* value: RouterBean(MainActivity1.class)
|
||||
*
|
||||
*/
|
||||
public interface ARouterPath {
|
||||
|
||||
/**
|
||||
* 例如:order分组下有这些信息,personal分组下有这些信息
|
||||
*
|
||||
* @return key:"/order/Order_MainActivity" 或 "/personal/Personal_MainActivity"
|
||||
* value: RouterBean==Order_MainActivity.class 或 RouterBean=Personal_MainActivity.class
|
||||
*/
|
||||
Map<String, RouterBean> getPathMap();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.xiangxue.arouter_api;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 跳转时 ,用于参数的传递
|
||||
*/
|
||||
public class BundleManager {
|
||||
|
||||
// Intent传输 携带的值,保存到这里
|
||||
private Bundle bundle = new Bundle();
|
||||
|
||||
// TODO 新增点
|
||||
// 底层业务接口
|
||||
private Call call;
|
||||
Call getCall() {
|
||||
return call;
|
||||
}
|
||||
void setCall(Call call) {
|
||||
this.call = call;
|
||||
}
|
||||
|
||||
public Bundle getBundle() {
|
||||
return this.bundle;
|
||||
}
|
||||
|
||||
// 对外界提供,可以携带参数的方法
|
||||
public BundleManager withString(@NonNull String key, @Nullable String value) {
|
||||
bundle.putString(key, value);
|
||||
return this; // 链式调用效果 模仿开源框架
|
||||
}
|
||||
|
||||
public BundleManager withBoolean(@NonNull String key, @Nullable boolean value) {
|
||||
bundle.putBoolean(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleManager withInt(@NonNull String key, @Nullable int value) {
|
||||
bundle.putInt(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleManager withSerializable(@NonNull String key, @Nullable Serializable object) {
|
||||
bundle.putSerializable(key, object);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleManager withBundle(Bundle bundle) {
|
||||
this.bundle = bundle;
|
||||
return this;
|
||||
}
|
||||
|
||||
// Derry只写到了这里,同学们可以自己增加 ...
|
||||
|
||||
// 直接完成跳转
|
||||
public Object navigation(Context context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
return RouterManager.getInstance().navigation(context, this);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
11
arouter_api/src/main/java/com/xiangxue/arouter_api/Call.java
Normal file
11
arouter_api/src/main/java/com/xiangxue/arouter_api/Call.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package com.xiangxue.arouter_api;
|
||||
|
||||
/**
|
||||
* 跨模块业务回调,空接口可集成拓展/实现
|
||||
*
|
||||
* 图片共享 组件 和 组件之间
|
||||
* Bean共享 组件 和 组件之间
|
||||
* ....
|
||||
*/
|
||||
public interface Call {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.xiangxue.arouter_api;
|
||||
|
||||
public interface ParameterGet {
|
||||
|
||||
/**
|
||||
* 目标对象.属性名 = getIntent().属性类型... 完成赋值操作
|
||||
* @param targetParameter 目标对象:例如:MainActivity 中的那些属性
|
||||
*/
|
||||
void getParameter(Object targetParameter);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.xiangxue.arouter_api;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.util.LruCache;
|
||||
|
||||
/**
|
||||
* 参数的 加载管理器
|
||||
* TODO 同学们:这是用于接收参数的
|
||||
*
|
||||
* 第一步:查找 Personal_MainActivity$$Parameter
|
||||
* 第二步:使用 Personal_MainActivity$$Parameter this 给他
|
||||
*/
|
||||
public class ParameterManager {
|
||||
|
||||
private static ParameterManager instance;
|
||||
|
||||
// private boolean isCallback;
|
||||
|
||||
public static ParameterManager getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (ParameterManager.class) {
|
||||
if (instance == null) {
|
||||
instance = new ParameterManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
// LRU缓存 key=类名 value=参数加载接口
|
||||
private LruCache<String, ParameterGet> cache;
|
||||
|
||||
private ParameterManager() {
|
||||
cache = new LruCache<>(100);
|
||||
}
|
||||
|
||||
// 为什么还要拼接,此次拼接 是为了寻找他
|
||||
static final String FILE_SUFFIX_NAME = "$$Parameter"; // 为了这个效果:Order_MainActivity + $$Parameter
|
||||
|
||||
// 使用者 只需要调用这一个方法,就可以进行参数的接收
|
||||
public void loadParameter(Activity activity) { // 必须拿到 Personal_MainActivity
|
||||
String className = activity.getClass().getName(); // className == Personal_MainActivity
|
||||
|
||||
ParameterGet parameterLoad = cache.get(className); // 先从缓存里面拿 如果有 如果没有
|
||||
if (null == parameterLoad) { // 缓存里面没东东 提高性能
|
||||
// 拼接 如:Order_MainActivity + $$Parameter
|
||||
// 类加载Order_MainActivity + $$Parameter
|
||||
try {
|
||||
// 类加载Personal_MainActivity + $$Parameter
|
||||
Class<?> aClass = Class.forName(className + FILE_SUFFIX_NAME);
|
||||
// 用接口parameterLoad = 接口的实现类Personal_MainActivity
|
||||
parameterLoad = (ParameterGet) aClass.newInstance();
|
||||
cache.put(className, parameterLoad); // 保存到缓存
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
parameterLoad.getParameter(activity); // 最终的执行 会执行我们生成的类
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
package com.xiangxue.arouter_api;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.LruCache;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.xiangxue.arouter_annotation.bean.RouterBean;
|
||||
|
||||
/**
|
||||
* 整个目标
|
||||
* 第一步:查找 ARouter$$Group$$personal ---> ARouter$$Path$$personal
|
||||
* 第二步:使用 ARouter$$Group$$personal ---> ARouter$$Path$$personal
|
||||
*/
|
||||
public class RouterManager {
|
||||
|
||||
private String group; // 路由的组名 app,order,personal ...
|
||||
private String path; // 路由的路径 例如:/order/Order_MainActivity
|
||||
|
||||
/**
|
||||
* 上面定义的两个成员变量意义:
|
||||
* 1.拿到ARouter$$Group$$personal 根据组名 拿到 ARouter$$Path$$personal
|
||||
* 2.操作路径,通过路径 拿到 Personal_MainActivity.class,就可以实现跳转了
|
||||
*/
|
||||
|
||||
// 单例模式
|
||||
private static RouterManager instance;
|
||||
|
||||
public static RouterManager getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (RouterManager.class) {
|
||||
if (instance == null) {
|
||||
instance = new RouterManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
// 提供性能 LRU缓存
|
||||
private LruCache<String, ARouterGroup> groupLruCache;
|
||||
private LruCache<String, ARouterPath> pathLruCache;
|
||||
|
||||
// 为了拼接,例如:ARouter$$Group$$personal
|
||||
private final static String FILE_GROUP_NAME = "ARouter$$Group$$";
|
||||
|
||||
private RouterManager() {
|
||||
groupLruCache = new LruCache<>(100);
|
||||
pathLruCache = new LruCache<>(100);
|
||||
}
|
||||
|
||||
/***
|
||||
* @param path 例如:/order/Order_MainActivity
|
||||
* * @return
|
||||
*/
|
||||
public BundleManager build(String path) {
|
||||
if (TextUtils.isEmpty(path) || !path.startsWith("/")) {
|
||||
throw new IllegalArgumentException("不按常理出牌 path乱搞的啊,正确写法:如 /order/Order_MainActivity");
|
||||
}
|
||||
|
||||
// 同学可以自己增加
|
||||
// ...
|
||||
|
||||
if (path.lastIndexOf("/") == 0) { // 只写了一个 /
|
||||
throw new IllegalArgumentException("不按常理出牌 path乱搞的啊,正确写法:如 /order/Order_MainActivity");
|
||||
}
|
||||
|
||||
// 截取组名 /order/Order_MainActivity finalGroup=order
|
||||
String finalGroup = path.substring(1, path.indexOf("/", 1)); // finalGroup = order
|
||||
|
||||
if (TextUtils.isEmpty(finalGroup)) {
|
||||
throw new IllegalArgumentException("不按常理出牌 path乱搞的啊,正确写法:如 /order/Order_MainActivity");
|
||||
}
|
||||
|
||||
// 证明没有问题,没有抛出异常
|
||||
this.path = path; // 最终的效果:如 /order/Order_MainActivity
|
||||
this.group = finalGroup; // 例如:order,personal
|
||||
|
||||
// TODO 走到这里后 grooup 和 path 没有任何问题 app,order,personal /app/MainActivity
|
||||
|
||||
return new BundleManager(); // Builder设计模式 之前是写里面的, 现在写外面吧
|
||||
}
|
||||
|
||||
// 真正的导航
|
||||
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
|
||||
public Object navigation(Context context, BundleManager bundleManager) {
|
||||
// 例如:寻找 ARouter$$Group$$personal 寻址 ARouter$$Group$$order ARouter$$Group$$app
|
||||
String groupClassName = context.getPackageName() + "." + FILE_GROUP_NAME + group;
|
||||
Log.e("derry >>>", "navigation: groupClassName=" + groupClassName);
|
||||
|
||||
|
||||
try {
|
||||
// TODO 第一步 读取路由组Group类文件
|
||||
ARouterGroup loadGroup = groupLruCache.get(group);
|
||||
if (null == loadGroup) { // 缓存里面没有东东
|
||||
// 加载APT路由组Group类文件 例如:ARouter$$Group$$order
|
||||
Class<?> aClass = Class.forName(groupClassName);
|
||||
// 初始化类文件
|
||||
loadGroup = (ARouterGroup) aClass.newInstance();
|
||||
|
||||
// 保存到缓存
|
||||
groupLruCache.put(group, loadGroup);
|
||||
}
|
||||
|
||||
if (loadGroup.getGroupMap().isEmpty()) {
|
||||
throw new RuntimeException("路由表Group报废了..."); // Group这个类 加载失败
|
||||
}
|
||||
|
||||
// TODO 第二步 读取路由Path类文件
|
||||
ARouterPath loadPath = pathLruCache.get(path);
|
||||
if (null == loadPath) { // 缓存里面没有东东 Path
|
||||
// 1.invoke loadGroup
|
||||
// 2.Map<String, Class<? extends ARouterLoadPath>>
|
||||
Class<? extends ARouterPath> clazz = loadGroup.getGroupMap().get(group);
|
||||
|
||||
// 3.从map里面获取 ARouter$$Path$$personal.class
|
||||
loadPath = clazz.newInstance();
|
||||
|
||||
// 保存到缓存
|
||||
pathLruCache.put(path, loadPath);
|
||||
}
|
||||
|
||||
// TODO 第三步 跳转
|
||||
if (loadPath != null) { // 健壮
|
||||
if (loadPath.getPathMap().isEmpty()) { // pathMap.get("key") == null
|
||||
throw new RuntimeException("路由表Path报废了...");
|
||||
}
|
||||
|
||||
// 最后才执行操作
|
||||
RouterBean routerBean = loadPath.getPathMap().get(path);
|
||||
|
||||
if (routerBean != null) {
|
||||
switch (routerBean.getTypeEnum()) {
|
||||
case ACTIVITY:
|
||||
Intent intent = new Intent(context, routerBean.getMyClass()); // 例如:getClazz == Order_MainActivity.class
|
||||
intent.putExtras(bundleManager.getBundle()); // 携带参数
|
||||
// context.startActivity(intent, bundleManager.getBundle()); // 大部分手机有问题,没有任何反应
|
||||
context.startActivity(intent);
|
||||
break;
|
||||
|
||||
case CALL:
|
||||
// OrderAddressImpl.class OrderBean getOrderBean
|
||||
Class<?> clazz = routerBean.getMyClass(); // OrderUserImpl BaseUser实体
|
||||
Call call = (Call) clazz.newInstance();
|
||||
bundleManager.setCall(call);
|
||||
return bundleManager.getCall();
|
||||
|
||||
//同学们可以自己扩展 类型
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
3
arouter_api/src/main/res/values/strings.xml
Normal file
3
arouter_api/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">ARouter_Api</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.xiangxue.arouter_api;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user