React Native之hardwareBackPress

1  hardwareBackPress

我們用hardwareBackPress來監(jiān)聽手機物理返回鍵


 
2 js那邊常用寫法

BackHandler.addEventListener('hardwareBackPress', this._back);

 
3  我們看下Android源代碼分析是怎么觸發(fā)到這里來的

1) ReactActivity.java里面的部分代碼如下

      @Override
      public void onBackPressed() {
        if (!mDelegate.onBackPressed()) {
          super.onBackPressed();
        }
      }

2 ) 進入onBackPressed()函數(shù)看看,在ReactActivityDelegate.java文件里面

      public boolean onBackPressed() {
        if (getReactNativeHost().hasInstance()) {
          getReactNativeHost().getReactInstanceManager().onBackPressed();
          return true;
        }
        return false;
      }

3)再次點擊onBackPressed函數(shù)進去看下

      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函數(shù)里面看下

      /**
       * Sends an event to the JS instance that the hardware back has been pressed.
       */
      public void emitHardwareBackPressed() {
        getReactApplicationContext()
            .getJSModule(RCTDeviceEventEmitter.class)
            .emit("hardwareBackPress", null);
      }

這里發(fā)現(xiàn)了Android原生向js發(fā)送了消息,所以我們監(jiān)聽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 運行結(jié)果

點擊主界面的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,執(zhí)行this.props.navigation.goBack()方法,都不會觸發(fā)hardwareBackPress監(jiān)聽所執(zhí)行的函數(shù)


 










作者:chen.yu
深信服三年半工作經(jīng)驗,目前就職游戲廠商,希望能和大家交流和學(xué)習(xí),
微信公眾號:編程入門到禿頭 或掃描下面二維碼
零基礎(chǔ)入門進階人工智能(鏈接)