菜刀文 2017-10-25 2481浏览量
App中每次页面跳转,都需要调用统一导航, 它用的非常频繁, 有必要对它进行一下梳理. 让他能用起来简单方便, 同时能支持各种常用的跳转业务场景.
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("smsto:10086"));
context.startActivity(intent);
如果项目分多个Module, Activity需要在各自Module的AndroidManifest.xml中声明,容易重复,不好统一管理.
//通过设置目标class跳转
Intent intent = new Intent();
intent.setClass(context,TargetActivity.class);
context.startActivity(intent);
A如果要跳转到TargetActivity, A要引用到TargetActivity. 造成:
- 如果项目多个Module开发,底层module不能跳转到高层Activity
内置H5要跳转 Native页面, 通过JsBidge把目标信息传过来.
方式1: 直接提供目标Activity的 Action 跳过去.
方式2: Native维护一个<描述,Activity信息>的Map, H5传过来Activiy的"描述", Native在Map中查到后,进行跳转.
一般H5会同时在"Android/ios"容器中, 所以最好的实践是:H5做跳转时不需要区分平台和版本. 如果利用Action跳转,
1)Action命名要符合两个平台的规范
2)如果Native不支持目标Action,还需要做跳转失败后处理.
1)维护<描述,Activity信息>的列表麻烦事,需要单独角色管理.
2)同样存的"Activity信息"也有问题1,2中提到的问题
处理跳转的Bridge类,可能拿不到context,这需要拿Application的Context,大家都判断略嫌麻烦.
比如2.0版本新加了"消息"功能,App1.0版本没有.
此时1.0版本的App中,"H5/push" 尝试打开"消息"页面, 肯定是不支持的. 这时候有几种策略:
- H5/Push能判断Native支持页面的能力,如果不支持,就不调用
- Native收到调用未知页面, 不做任何动作.
- Native收到调用未知页面, 提示这是新版功能,建议更新版本.
跳转到目标页面前,能统一加参数.
实现比如打点, 添加通用参数操作.
考虑这种业务场景: App有 A,B,C三个页面, 提供给外部调用.
这时候一般两种实现方式:
方式1: A,B,C的Activity 在AndroidManifest.xml中export=true,并且设置 intent-filter
方式2: App设置一个统一的Router-Activity, 外部跳转到A,B,C 都统一先统一到Router-Activity, 他在拉起A,B,C
除非真的提供通用的功能(拍照/图片处理/..)给外部调用, 否则export一个Activity是不必要也不安全的. 为了安全,App不会export大量的Activity. 这意味着通过这种机制, 外部能调用内部的功能较少.
优点:
缺点:
外部跳转需要一个Activity中转一下,直观上感觉效率低一些. 但是实际感觉基本没有影响.
根据问题和业务场景, 我们的"统一跳转"的需求也基本明确:
- "声明/使用" 简单.
ARouterARouter-github 很好的解决了上述问题.
下面是他的对应的方案.
- 每个Activity在类中自声明,"代码-路径"对应一目了然
@Route(path = "/test/activity")
public class YourActivity extend Activity {
...
}
- 跳转新页面简单,不需要知道目标ActivityContext,intent-filter,目标的Activity
ARouter.getInstance().build(path).with(bundle).navigation();
所有页面可以统一定义. 一目了然
String PAGE_MAIN = "/navigateTo/main";
String PAGE_H5 = "/navigateTo/h5";
String PAGE_WEEX = "/navigateTo/weex";
...
public class SchameFilterActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//安全/版本校验
....
Uri uri = getIntent().getData();
ARouter.getInstance().build(uri).navigation();
finish();
}
}
ARouter.getInstance().build("/test/1").navigation(this, new NavigationCallback() {
@Override
public void onFound(Postcard postcard) {
...
}
@Override
public void onLost(Postcard postcard) {
//可以处理,提示升级版本之类
}
});
// 实现DegradeService接口,并加上一个Path内容任意的注解即可
@Route(path = "/xxx/xxx")
public class DegradeServiceImpl implements DegradeService {
@Override
public void onLost(Context context, Postcard postcard) {
// do something.
}
@Override
public void init(Context context) {
}
}
// 实现PathReplaceService接口,并加上一个Path内容任意的注解即可
@Route(path = "/xxx/xxx") // 必须标明注解
public class PathReplaceServiceImpl implements PathReplaceService {
/**
* For normal path.
*
* @param path raw path
*/
String forString(String path) {
return path; // 按照一定的规则处理之后返回处理后的结果
}
/**
* For uri type.
*
* @param uri raw uri
*/
Uri forUri(Uri uri) {
return url; // 按照一定的规则处理之后返回处理后的结果
}
}
ARouter最后是通过下面方式跳转的.
//_ARouter.java
Intent intent = new Intent(currentContext,postcard.getDestination());
intent.putExtras(postcard.getExtras());
所以要AROUTER需要维护一个 Path和Activity class的对应关系.
他利用
BUILDTOOLS_VERSION=25.0.0
使用:
compile "com.android.support:support-v4:${SUPPORT_LIB_VERSION}"
buildToolsVersion BUILDTOOLS_VERSION
HashMap通过hashcode对其内容进行快速查找,而 TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的)
你可以将Instrumentation理解为一种没有图形界面
的,具有启动能力的,用于监控其他类(用Target
Package声明)的工具类。任何想成为Instrumentation的类必须继承android.app.Instrumentation。
下面是这个类的解释:
“Base class for implementing application instrumentation code. When running with instrumentation turned on, this class will be instantiated for you before any of the application code, allowing you to monitor all of the interaction the system has with the application. An Instrumentation implementation is described to the system through an AndroidManifest.xml's tag.“
CountDownLatch的一个非常典型的应用场景是:有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以继续往下执行。假如我们这个想要继续往下执行的任务调用一个CountDownLatch对象的await()方法,其他的任务执行完自己的任务后调用同一个CountDownLatch对象上的countDown()方法,这个调用await()方法的任务将一直阻塞等待,直到这个CountDownLatch对象的计数值减到0为止。
CPU_COUNT = Runtime.getRuntime().availableProcessors()
// 捕获多线程处理中的异常
thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable ex) {
ARouter.logger.info(Consts.TAG, "Running task appeared exception! Thread [" + thread.getName() + "], because [" + ex.getMessage() + "]");
}
});
build classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
使用 annotationProcessor
dependencies {
annotationProcessor project(':arouter-compiler')
}
int flags = postcard.getFlags();
if (-1 != flags) {
intent.setFlags(flags);
} else if (!(currentContext instanceof Activity)) {
// Non activity, need less one flag.
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
//设置WareHouse
public interface IRouteGroup {
/**
* Fill the atlas with routes in group.
*/
void loadInto(Map<String, RouteMeta> atlas);
}
iGroupInstance.loadInto(Warehouse.routes);
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
集结各类场景实战经验,助你开发运维畅行无忧