問題來源
1.我們的項目中用到了React-Navigation來處理路由默终,其中用的又是StackNavigation绢涡。
2.使用的是ActivityA橫屏承載ReactNative的js頁面猩谊,并且對Android的虛擬按鍵進行了統(tǒng)一處理
3.最近突然有一個需求尺碰,需要再搞一個ActivityB承載一個單頁面的豎屏視圖
問題暴露
上面的需求實現(xiàn)起來很簡單
1.定義一個ActivityB
public class ActivityB extends ReactActivity {
@Override
protected String getMainComponentName() {
return "ActivityB";
}
@Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new ReactActivityDelegate(this, getMainComponentName()) {
@Override
protected ReactRootView createRootView() {
//處理手勢四啰,也可以不用實現(xiàn)這個
return new RNGestureHandlerEnabledRootView(ActivityB.this);
}
@Nullable
@Override
protected Bundle getLaunchOptions() {
Intent intent = getIntent();
String flag="";
Bundle bundle = new Bundle();
if (intent.hasExtra("flag")){
flag = intent.getStringExtra("flag");
bundle.putString("flag",flag);
}
return bundle;
}
};
}
}
2.在清單文件中聲明
<activity android:name=".ActivityB"
android:screenOrientation="portrait"/>
3.實現(xiàn)橋接方法讓ReactNative調(diào)用,并且添加到package中记餐,最終注冊在Application中
public IntentModule(@NonNull ReactApplicationContext reactContext) {
super(reactContext);
reactContext.addActivityEventListener(new ActivityEventListener() {
@Override
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
if (requestCode==110&&resultCode==111){
if (data!=null){
WritableMap map = Arguments.createMap();
if (data.hasExtra("data")) {
String datas = data.getStringExtra("data");
map.putString("data",datas);
}
if (data.hasExtra("uri")) {
String uri = data.getStringExtra("uri");
map.putString("uri",uri);
}
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("ActivityB", map);
}
}
}
@Override
public void onNewIntent(Intent intent) {
}
});
}
@NonNull
@Override
public String getName() {
return "IntentModule";
}
@ReactMethod
public void jumpCameraActivityForResult(ReadableMap map){
String flag = "";
if (map.hasKey("flag")){
flag = map.getString("flag");
}
Intent intent = new Intent(getCurrentActivity(), ActivityB.class);
if (!TextUtils.isEmpty(flag)){
intent.putExtra("flag",flag);
}
Objects.requireNonNull(getCurrentActivity()).startActivityForResult(intent,CAMERA_REQUEST_CODE);
}
@ReactMethod
public void finish(ReadableMap map){
String data="";
if (map.hasKey("data")){
data = map.getString("data");
}
String uri="";
if (map.hasKey("uri")){
uri=map.getString("uri");
}
Intent intent=new Intent();
if (!TextUtils.isEmpty(data)) {
intent.putExtra("data", data);
}
if (!TextUtils.isEmpty(uri)) {
intent.putExtra("uri", uri);
}
Objects.requireNonNull(getCurrentActivity()).setResult(ACTIVITY_RESULT_CODE,intent);
getCurrentActivity().finish();
}
4.直接在首頁中點擊進入的二級頁面中加入跳轉驮樊,并且點擊返回
最終會發(fā)現(xiàn)除了ActivityB返回了,二級頁面也不在了。囚衔。挖腰。。练湿。猴仑。。
分析問題
1.首先在跳轉ActivityB之前我打印了路由棧中的所有路由
2.在ActivityB退出之后我又打印了路由棧中的所有路由
經(jīng)過對比確實發(fā)現(xiàn)二級頁面不見了(不在棧中了)
3.我在路由的pop肥哎,rest等頁面分別打了日志辽俗,發(fā)現(xiàn)并沒有被調(diào)用
排除了方法誤調(diào)導致的問題
4.去github的issuse里面去看看有沒有別人遇到過這個問題
5.百度(無果)
查了一圈發(fā)現(xiàn)沒有人提到這個問題(得嘞,還得自己排查)
6.我后來就琢磨是不是把ActivityB的虛擬返回去掉篡诽,并且ActivityB顯示全屏是不是可以解決這個問題
嘗試后發(fā)現(xiàn)果然可以崖飘。。霞捡。
7.那沒毛病坐漏,肯定是ReactNative的返回處理和原生的返回處理都被執(zhí)行了,導致不僅ActivityB退出了碧信,ReactNative中的二級頁面也退出了
8.去看看ReactActivity是如何處理返回的赊琳,果不其然發(fā)現(xiàn)優(yōu)先處理ReactNative內(nèi)部的返回
@Override
public void onBackPressed() {
if (!mDelegate.onBackPressed()) {
super.onBackPressed();
}
}
到這里就簡單了我不讓他走ReactNative內(nèi)部的返回不就行了,返回false給他
到這里本次的問題就圓滿解決了砰碴。
附上ActivityB的整體源碼
public class ActivityB extends ReactActivity {
@Override
protected String getMainComponentName() {
return "ActivityB";
}
@Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new ReactActivityDelegate(this, getMainComponentName()) {
@Override
public boolean onBackPressed() {
return false;
}
@Nullable
@Override
protected Bundle getLaunchOptions() {
Intent intent = getIntent();
String flag="";
Bundle bundle = new Bundle();
if (intent.hasExtra("flag")){
flag = intent.getStringExtra("flag");
bundle.putString("flag",flag);
}
return bundle;
}
};
}
}