背景
为了保持三端统一的开发体验,目前我们工程中用到的路由跳转都是使用原生端封装好的方法进行页面跳转,比如点击登录
按钮,在HTML或者weex当中会统一调用如下格式的代码:
("ext.util.router",{
path: urlPath
},function (data) {
//data为原生回调js的参数
}
)
params当中的url是当前需要需要跳转的页面地址,我们采用scheme(weex/native)://pageUrl?params="xxx
"的URI字符串来定义路由跳转规则,scheme
可以传weex或者nativie,android原生端通过该标识来区分是跳转到原生Activity还是WeexActivity页面.
页面间参数传递
有如下场景:列表list.js
界面跳转到详情detal.js?id="666"
- 如何在详情界面取到id的值?
android的原生代码当中提供了renderByUrl
的方法来渲染界面,同时传递了BUNDLE_URL
的参数:
protected void renderPageByURL(String url, String jsonInitData) {
CommonUtils.throwIfNull(mContainer, new RuntimeException("Can't render page, container is null"));
Map<String, Object> options = new HashMap<>();
options.put(WXSDKInstance.BUNDLE_URL, url);
mInstance.renderByUrl(
getPageName(),
url,
options,
jsonInitData,
WXRenderStrategy.APPEND_ASYNC);
}
这个url在js代码中可以通过weex.config.bundleUrl
获取到,通过解析url,进行正则匹配和URI解码,
就能够截取到相应的参数数据,native ->weex(native)同理,weex页面的正向传参就此解决.
指定weex页面返回
- 如何实现返回到指定页面并反向传值?
有如下场景:A页面跳转到B页面,B再跳转到C,C页面操作完毕后返回A页面,并且带回了一些参数:
WeexActivity是js的加载容器,启动模式为standard标准模式,意味着每加载一个js文件,就在栈顶新建一个Activity,既然只有一个WeexActivity,那么就不能通过普通的Intent(context, WXPageActivity::class.java)
跳转到指定的类文件,目前android端采用了如下方案:
- 首先自定义一个WxManager用来管理WeexActivity的实例:
public class WxManager{
private static final WxManagerourInstance = new WxManager();
private static HashMap<String, Activity> activityHashMap = new HashMap<>();
public static WxManager getInstance() {
return ourInstance;
}
private WxManager() {
}
public void registerActivity(String path, Activity activity) {
if (activity != null && !TextUtils.isEmpty(path)) {
activityHashMap.put(path, activity);
}
}
}
在WeexActivity 的OnCreate方法中,把对应的path和activity注册到WxManager
- android原生端在收到weex发送的回退到指定页面的事件后,调用方法进行比对,path不一致则销毁当前Activity,直到回退到指定界面:
val activityList = ActivityUtils.getActivityList()
val returnActivity = WxManager.getInstance().getActivity(returnPath)
for (i in activityList.indices.reversed()) {
val activity = activityList[i]
if (activity == returnActivity) {
return
}
Intent().apply {
putExtra("refresh",refresh)
activity.setResult(Activity.RESULT_OK, this)
activity.finish()
}
}
回退到指定界面的问题解决了,那么该如何反向传递参数呢?android提供了startActivityForResult方法:
如果想在Activity中得到新打开Activity 关闭后返回的数据,需要使用系统提供的startActivityForResult(Intent intent, int requestCode)方法打开新的Activity,新的Activity 关闭后会向前面的Activity传回数据,为了得到传回的数据,必须在前面的Activity中重写onActivityResult(int requestCode, int resultCode, Intent data)方法。
因此我们在启动WeexActivity 时默认调用startActivityForResult
:
//启动一个新的WeexActivity 页面
public static void start(Context context, String url) {
Intent intent = new Intent(context, WXPageActivity.class);
intent.setData(Uri.parse(url));
if (context instanceof Activity) {
((Activity) context).startActivityForResult(intent, REQUEST_CODE);
} else {
context.startActivity(intent);
}
}
在OnActivityResult
方法中进行参数接收:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE) {
boolean needRefresh = data.getBooleanExtra("refresh", false);
if (needRefresh) {
refresh();
}
}
super.onActivityResult(requestCode, resultCode, data);
}
refresh方法通过通过fireGlobalEventCallback把数据传递到weex页面。
public void refresh() {
if (mInstance != null) {
Map<String, Object> params = new HashMap<>();
mInstance.fireGlobalEventCallback("weexRefreshData", params);
}
}
在weex页面监听weexRefreshData
事件并处理:
globalEvent.addEventListener('weexRefreshData', function(e) {
});
自此反向传参实现完成.