React Native之hardwareBackPress

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011068702/article/details/83388372

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监听所执行的函数

猜你喜欢

转载自blog.csdn.net/u011068702/article/details/83388372