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
深信服三年半工作经验,目前就职游戏厂商,希望能和大家交流和学习,
微信公众号:编程入门到秃头 或扫描下面二维码
零基础入门进阶人工智能(链接)