React Native之hardwareBackPress
1 hardwareBackPress
我们用hardwareBackPress来监听手机物理返回键
2 js那边常用写法
BackHandler.addEventListener('hardwareBackPress', this._back);
3 我们看下Android源代码分析是怎么触发到这里来的
1) ReactActivity.java里面的部分代码如下
@Override
public void onBackPressed() {
if (!mDelegate.onBackPressed()) {
super.onBackPressed();
}
}
2 ) 进入onBackPressed()函数看看,在ReactActivityDelegate.java文件里面
public boolean onBackPressed() {
if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager().onBackPressed();
return true;
}
return false;
}
3)再次点击onBackPressed函数进去看下
public void onBackPressed() {
UiThreadUtil.assertOnUiThread();
ReactContext reactContext = mCurrentReactContext;
if (reactContext == null) {
// Invoke without round trip to JS.
FLog.w(ReactConstants.TAG, "Instance detached from instance manager");
invokeDefaultOnBackPressed();
} else {
DeviceEventManagerModule deviceEventManagerModule =
reactContext.getNativeModule(DeviceEventManagerModule.class);
deviceEventManagerModule.emitHardwareBackPressed();
}
}
4) 进到emitHardwareBackPressed函数里面看下
/**
* Sends an event to the JS instance that the hardware back has been pressed.
*/
public void emitHardwareBackPressed() {
getReactApplicationContext()
.getJSModule(RCTDeviceEventEmitter.class)
.emit("hardwareBackPress", null);
}
这里发现了Android原生向js发送了消息,所以我们监听hardwareBackPress就有反映
4 测试代码如下
App.js文件如下
import React from 'react';
import { View, Text, Button, NativeModules, BackHandler} from 'react-native';
import { createStackNavigator } from 'react-navigation';
var toast = NativeModules.MyToast;
class HomeScreen extends React.Component {
constructor(props) {
super(props);
console.log("HomeScreen constructor start");
}
static navigationOptions = {
title : 'HomeScreen',
}
componentDidMount = () => {
this.didFocusListener = this.props.navigation.addListener(
'didFocus',
(obj) => {
console.log("HomeScreen didFocus start");
BackHandler.addEventListener('hardwareBackPress', this._back);
}
);
this.didBlurListener = this.props.navigation.addListener(
'didBlur',
(obj) => {console.log('HomeScreen didBlur start')}
);
console.log("HomeScreen componentDidMount start")
}
componentWillUnmount() {
console.log("HomeScreen componentWillUnmount start")
this.didFocusListener.remove();
this.didBlurListener.remove();
}
render() {
var testID = 'chenyu';
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Text testID = {testID} onPress = {() => this._goto()}>Home Screen</Text>
<Button onPress={() => this.props.navigation.navigate('Details', {
itemId:100,
otherParam:'chenyu',
})} title = "go to Details"/>
<Button
title="Go back"
onPress={() => this.props.navigation.goBack()}
/>
</View>
);
}
_show(value) {
console.log(value);
}
_goto = () => {
toast.show();
}
_back = () => {
console.log("home back");
}
}
class DetailsScreen extends React.Component {
constructor(props) {
super(props);
console.log("DetailsScreen constructor start");
this.didFocusListener = this.props.navigation.addListener(
'didFocus',
(obj) => {
console.log("DetailsScreen didFocus start");
BackHandler.addEventListener('hardwareBackPress', this._back);
}
);
this.didBlurListener = this.props.navigation.addListener(
'didBlur',
(obj) => {console.log('DetailsScreen didBlur start')}
);
}
_back = () => {
console.log("detail back");
}
static navigationOptions = ({navigation}) => {
return {
title : navigation.getParam('otherParam', 'no-values'),
};
};
componentDidMount = () => {
console.log("DetailsScreen componentDidMount start")
}
componentWillUnmount() {
console.log("DetailsScreen componentWillUnmount start")
this.didFocusListener.remove();
this.didBlurListener.remove();
}
render() {
const {navigation} = this.props;
const itemId = navigation.getParam('itemId', 'no-values');
const otherParam = navigation.getParam('otherParam', 'no-values');
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Text>itemId:{JSON.stringify(itemId)}</Text>
<Text>otherParam:{JSON.stringify(otherParam)}</Text>
<Button
title="Go to Details... again"
onPress={() => this.props.navigation.push('Details', {
itemId: Math.floor(Math.random() * 100),
})}
/>
<Button
title="Go to Home"
onPress={() => this.props.navigation.navigate('Home')}
/>
<Button
title="Go back"
onPress={() => this.props.navigation.goBack()}
/>
<Button
title="Go popToTop"
onPress={() => this.props.navigation.popToTop()}
/>
</View>
);
}
}
const RootStack = createStackNavigator(
{
Home: HomeScreen,
Details: DetailsScreen,
},
{
initialRouteName: 'Home',
}
);
export default class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return <RootStack/>;
}
}
5 运行结果
点击主界面的GO TO DETAILS,进入详细页面,然后分别按下2次back键,日志如下
10-27 23:39:32.498 917 1031 I ReactNativeJS: detail back
10-27 23:39:32.498 917 1031 I ReactNativeJS: home back
10-27 23:39:32.784 917 1031 I ReactNativeJS: DetailsScreen componentWillUnmount start
10-27 23:39:32.790 917 1031 I ReactNativeJS: HomeScreen didFocus start
10-27 23:39:51.164 917 1031 I ReactNativeJS: detail back
10-27 23:39:51.165 917 1031 I ReactNativeJS: home back
10-27 23:39:51.165 917 1031 I ReactNativeJS: detail back
10-27 23:39:51.165 917 1031 I ReactNativeJS: home back
10-27 23:39:51.165 917 1031 I ReactNativeJS: detail back
10-27 23:39:51.165 917 1031 I ReactNativeJS: home back
10-27 23:39:51.165 917 1031 I ReactNativeJS: home back
10-27 23:39:51.165 917 1031 I ReactNativeJS: detail back
10-27 23:39:51.166 917 1031 I ReactNativeJS: detail back
10-27 23:39:51.166 917 1031 I ReactNativeJS: home back
10-27 23:39:51.166 917 1031 I ReactNativeJS: detail back
10-27 23:39:51.166 917 1031 I ReactNativeJS: home back
10-27 23:39:51.166 917 1031 I ReactNativeJS: home back
10-27 23:39:51.621 917 1031 I ReactNativeJS: HomeScreen componentWillUnmount start
我们点击标题栏的返回按钮,和点击GO BACK,执行this.props.navigation.goBack()方法,都不会触发hardwareBackPress监听所执行的函数
作者:chen.yu
深信服三年半工作经验,目前就职游戏厂商,希望能和大家交流和学习,
微信公众号:编程入门到秃头 或扫描下面二维码
零基础入门进阶人工智能(链接)