背景
為了保持三端統(tǒng)一的開發(fā)體驗(yàn),目前我們工程中用到的路由跳轉(zhuǎn)都是使用原生端封裝好的方法進(jìn)行頁(yè)面跳轉(zhuǎn),比如點(diǎn)擊登錄 按鈕,在HTML或者weex當(dāng)中會(huì)統(tǒng)一調(diào)用如下格式的代碼:
("ext.util.router",{
path: urlPath
},function (data) {
//data為原生回調(diào)js的參數(shù)
}
)
params當(dāng)中的url是當(dāng)前需要需要跳轉(zhuǎn)的頁(yè)面地址,我們采用scheme(weex/native)://pageUrl?params="xxx"的URI字符串來(lái)定義路由跳轉(zhuǎn)規(guī)則,scheme可以傳weex或者nativie,android原生端通過(guò)該標(biāo)識(shí)來(lái)區(qū)分是跳轉(zhuǎn)到原生Activity還是WeexActivity頁(yè)面.
頁(yè)面間參數(shù)傳遞
有如下場(chǎng)景:列表list.js界面跳轉(zhuǎn)到詳情detal.js?id="666"
- 如何在詳情界面取到id的值?
android的原生代碼當(dāng)中提供了renderByUrl的方法來(lái)渲染界面,同時(shí)傳遞了BUNDLE_URL的參數(shù):
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);
}
這個(gè)url在js代碼中可以通過(guò)weex.config.bundleUrl獲取到,通過(guò)解析url,進(jìn)行正則匹配和URI解碼,
就能夠截取到相應(yīng)的參數(shù)數(shù)據(jù),native ->weex(native)同理,weex頁(yè)面的正向傳參就此解決.
指定weex頁(yè)面返回
- 如何實(shí)現(xiàn)返回到指定頁(yè)面并反向傳值?
有如下場(chǎng)景:A頁(yè)面跳轉(zhuǎn)到B頁(yè)面,B再跳轉(zhuǎn)到C,C頁(yè)面操作完畢后返回A頁(yè)面,并且?guī)Щ亓艘恍﹨?shù):
WeexActivity是js的加載容器,啟動(dòng)模式為standard標(biāo)準(zhǔn)模式,意味著每加載一個(gè)js文件,就在棧頂新建一個(gè)Activity,既然只有一個(gè)WeexActivity,那么就不能通過(guò)普通的Intent(context, WXPageActivity::class.java)跳轉(zhuǎn)到指定的類文件,目前android端采用了如下方案:
- 首先自定義一個(gè)WxManager用來(lái)管理WeexActivity的實(shí)例:
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方法中,把對(duì)應(yīng)的path和activity注冊(cè)到WxManager
- android原生端在收到weex發(fā)送的回退到指定頁(yè)面的事件后,調(diào)用方法進(jìn)行比對(duì),path不一致則銷毀當(dāng)前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()
}
}
回退到指定界面的問(wèn)題解決了,那么該如何反向傳遞參數(shù)呢?android提供了startActivityForResult方法:
如果想在Activity中得到新打開Activity 關(guān)閉后返回的數(shù)據(jù),需要使用系統(tǒng)提供的startActivityForResult(Intent intent, int requestCode)方法打開新的Activity,新的Activity 關(guān)閉后會(huì)向前面的Activity傳回?cái)?shù)據(jù),為了得到傳回的數(shù)據(jù),必須在前面的Activity中重寫onActivityResult(int requestCode, int resultCode, Intent data)方法。
因此我們?cè)趩?dòng)WeexActivity 時(shí)默認(rèn)調(diào)用startActivityForResult:
//啟動(dòng)一個(gè)新的WeexActivity 頁(yè)面
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方法中進(jìn)行參數(shù)接收:
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方法通過(guò)通過(guò)fireGlobalEventCallback把數(shù)據(jù)傳遞到weex頁(yè)面。
public void refresh() {
if (mInstance != null) {
Map<String, Object> params = new HashMap<>();
mInstance.fireGlobalEventCallback("weexRefreshData", params);
}
}
在weex頁(yè)面監(jiān)聽weexRefreshData事件并處理:
globalEvent.addEventListener('weexRefreshData', function(e) {
});
自此反向傳參實(shí)現(xiàn)完成.