ReactNative原生集成-Android


目錄

  • 1)搭建-原生集成rn
  • 2)demo-包含搭建過程源碼
  • 3)訪問原生側常量
  • 4)訪問原生側方法
    • 4.1)void無返回
    • 4.2)有返回回調
  • 5)原生啟動RN
    • 5.1)RN獲取Activity傳遞的Intent數據
    • 5.2)startActivityForResult返回Intent數據給Activity
  • 6)RN啟動原生
    • 6.1)Activity獲取RN傳遞的Intent數據
    • 6.2)startActivityForResult返回Intent數據給RN
    • 6.3)原生發送通知給RN
  • 7)UI互嵌
    • 7.1)原生界面內部分使用RN的界面
    • 7.2)RN界面內部分使用原生的界面

1)搭建-原生集成rn

  • react-native init 工程名
  • copy原Android工程至Rn工程/android中,配置gradle
  • app的gradle中加入
 dependencies {
     ...
     compile "com.facebook.react:react-native:+" // From node_modules.
 }
  • 項目gradle中加入
allprojects {
    repositories {
        ...
        maven {
            // All of React Native (JS, Android binaries) is installed from npm
            url "$rootDir/../node_modules/react-native/android"
        }
    }
    ...
}
  • 配置權限
<uses-permission android:name="android.permission.INTERNET" />
<!-開發者菜單 可不用->
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
  • 配置Application
public class MainApplication extends Application implements ReactApplication {

    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
            //Debug模式,這個模式才能在JS里作調試
            return BuildConfig.DEBUG;
        }

        @Override
        protected List<ReactPackage> getPackages() {
            //返回帶有官方已有的package的集合
            return Arrays.<ReactPackage>asList(
                    new MainReactPackage()
            );
        }
    };

    @Override
    public ReactNativeHost getReactNativeHost() {
        return mReactNativeHost;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        SoLoader.init(this, /* native exopackage */ false);
    }
}
  • Android 6.0(API level 23)或更高版本,開發版本中會要求打開懸浮窗(overlay)權限,生產版本則不要求,代碼可不用特別配置
  • 新建Activity
public class FirstReactActivity extends ReactActivity {

    @Override
    protected String getMainComponentName() {
        return "FirstReactComponent";  //注冊的react組件名,RN里要用到
    }
}
  • 新建RN-Component
export default class FirstReactComponent extends Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          大家好,我是React界面release
        </Text>
      </View>
    );
  }
}
  • 在RN的入口文件處注冊此Component,注意所有暴露給原生的Component都需要在入口文件處注冊。
    ~/index.android.js
import FirstReactComponent from './src/FirstReactComponent';
...
//暴露給原生使用
AppRegistry.registerComponent('FirstReactComponent', () => FirstReactComponent);
  • 打開Packager服務
    ~/工程根目錄
npm start
ReactNative原生集成-Android
  • 生產打release包
//創建keystore并配置gradle
    signingConfigs {
        release {
            storeFile file("/Users/tugaofeng/tgf/study/rn/studyRn_Native/studyRn_Native_keystore")
            storePassword "123456"
            keyAlias "studyRn_Native_keystore"
            keyPassword "123456"
        }
    }
    buildTypes {
        release {
            ...
            signingConfig signingConfigs.release
        }
    }
//創建assets目錄 ./android/app/src/main/assets
//創建離線bundle和打包本地資源
react-native bundle --entry-file index.android.js --bundle-output ./android/app/src/main/assets/index.android.bundle --platform android --assets-dest ./android/app/src/main/res/ --dev false
//打簽名包即可
cd android && ./gradlew assembleRelease
//進入目錄安裝apk  ./android/app/build/outputs/apk/release
adb install app-release.apk 

2)demo

demo

Android快照

RN快照
  • 創建一個原生模塊,繼承了ReactContextBaseJavaModule的Java類,內部可以實現一些JavaScript所需的功能
public class MyNativeBridgeModule extends ReactContextBaseJavaModule {

    //定義全局回調,RN->原生  startActivityForResult 返回數據給之前的 RNActivity
    private Callback secondActivityOnActivityResultCallback;
    //定義全局rnContext
    private ReactApplicationContext rnContext;

    public MyNativeBridgeModule(ReactApplicationContext reactContext) {
        super(reactContext);
        rnContext = reactContext;
        //定義監聽 RN->原生  startActivityForResult 返回數據給之前的 RNActivity
        reactContext.addActivityEventListener(mActivityEventListener);
    }

    //重寫此方法,
    //可在RN端通過React.NativeModules.NativeBridge標記使用此模塊
    @Override
    public String getName() {
        return "MyNativeBridgeModule";
    }

    //此方法可被RN端訪問常量
    @Nullable
    @Override
    public Map<String, Object> getConstants() {
        final Map<String, Object> constants = new HashMap<String, Object>();
        constants.put("Duration_Short", Toast.LENGTH_SHORT);
        constants.put("Duration_Long", Toast.LENGTH_LONG);
        constants.put("Native_Constants_A", "我是Native常量值");
        return constants;
    }

    //@ReactMethod 此注解定義與RN端的調用方法
    @ReactMethod
    public void showToast(String msg, int duration) {
        Toast.makeText(getReactApplicationContext(), msg, duration).show();
    }

    //方法的返回類型必須為void,跨端訪問為異步進行,需要返回值須寫回調
    @ReactMethod
    public void testCallBack(String msg, Callback successCB, Callback errorCB) {
        try {
            String result = msg + " ,但我被testCallBack方法修改了";
            successCB.invoke(result);
        } catch (Exception e) {
            errorCB.invoke("異常:" + e.getMessage());
        }
    }

    //實例:原生->RN 獲取之前Activity傳遞的數據
    @ReactMethod
    public void getDataFromIntent(Callback successCB, Callback errorCB) {
        try {
            Activity currentActivity = getCurrentActivity();
            String intentString = currentActivity.getIntent().getStringExtra("intentData");
            successCB.invoke(intentString);
        } catch (Exception e) {
            errorCB.invoke("異常:" + e.getMessage());
        }
    }

    //實例:原生->RN  startActivityForResult 返回數據給之前的Activity
    @ReactMethod
    public void finishActivityForResult(String msg) {
        Activity currentActivity = getCurrentActivity();
        Intent intent = new Intent();
        intent.putExtra("intentData", msg);
        currentActivity.setResult(Activity.RESULT_OK, intent);
        currentActivity.finish();
    }

    //實例: RN->原生  打開新的Activity
    //實際項目中可進行實際封裝
    @ReactMethod
    public void startNewActivityByString(String activityName, String data, Callback resultCB) {
        Activity currentActivity = getCurrentActivity();
        //此處采用隱式啟動,方便封裝。若顯示啟動,需要反射獲取class,或業務層上做kv映射。
        Intent intent = new Intent("com.tgf.studyrn_native_android.SecondActivity");
        //此處采用顯示啟動,需要反射
//        Class aimActivity = null;
//        try {
//            aimActivity = Class.forName("com.tgf.studyrn_native_android.SecondActivity");
//        } catch (ClassNotFoundException e) {
//            e.printStackTrace();
//        }
//        Intent intent = new Intent(currentActivity,aimActivity);

        //將回調函數賦值給全局變量,以便全局callback在mActivityEventListener中使用
        secondActivityOnActivityResultCallback = resultCB;
        currentActivity.startActivityForResult(intent, 1002);
    }

    //實例:RN->原生  startActivityForResult 返回數據給之前的 RNActivity
    //方式一 : Callback回調
    //方式二 : 發送通知
    private final ActivityEventListener mActivityEventListener = new BaseActivityEventListener() {
        @Override
        public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent intent) {
            switch (requestCode) {
                case 1002:
                    //方式一 : Callback回調
//                    try {
//                        secondActivityOnActivityResultCallback.invoke(intent.getStringExtra("intentData"));
//                    }catch (Exception e){
//                    }
                    //方式二 : 發送通知
                    rnContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("notify", intent.getStringExtra("intentData"));
                    break;
            }
        }
    };
}
  • 創建自定義的ReactPackage,并在其中注冊第一步創建的原生模塊
public class MyReactPackage implements ReactPackage {
    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();  //return null編譯時會出錯,要改寫成返回空集合
    }

    //注冊Native模塊
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        //注冊自定義的Native模塊
        modules.add(new MyNativeBridgeModule(reactContext)); 
        return modules;
    }

    @Override
    public List<Class<? extends JavaScriptModule>> createJSModules() {
        return Collections.emptyList(); //return null編譯時會出錯,要改寫成返回空集合
    }
}
  • 在工程Application中,加入自定義的ReactPackage
    ~/MainApplication.java
        @Override
        protected List<ReactPackage> getPackages() {
            //返回帶有官方已有的package的集合
            return Arrays.<ReactPackage>asList(
                    new MainReactPackage(),
                    new MyReactPackage()  //加入自定義的Package類
            );
        }
  • Android側的RNActivity類,繼承了ReactActivity
    ~/FirstReactActivity.java
public class FirstReactActivity extends ReactActivity {

    @Override
    protected String getMainComponentName() {
        return "FirstReactComponent";  //注冊的react組件名,一會在JS里要用到
    }

    //如果回調時不需要回到RN端處理,
    //也可此處定義onActivityResult
    //而不是在MyNativeBridgeModule中寫監聽
//    @Override
//    public void onActivityResult(int requestCode, int resultCode, Intent data) {
//        super.onActivityResult(requestCode, resultCode, data);
//        switch (requestCode){
//            case 1002:
//                Toast.makeText(this,data.getStringExtra("intentData"),Toast.LENGTH_SHORT).show();
//                break;
//        }
//    }
}
  • RN側的示例代碼
    ~/FirstReactComponent.js
export default class FirstReactComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      title:'大家好,我是React界面',
      intentData:'',
    };
  }

  //調用原生方法 showToast
  _showToast = ()=>{
    NativeModules.MyNativeBridgeModule.showToast('調用原生Toast',NativeModules.MyNativeBridgeModule.Duration_Short);
  }

  //調用原生方法 并獲取回調結果
  _testCallback = ()=>{
    NativeModules.MyNativeBridgeModule.testCallBack(this.state.title,
      (result)=>{
        console.log(result);
        //獲取了回調結果,并修改了state的title
        this.setState({
          title:result,
        })
      },
      (error)=>{
        console.log(error);
      }
    );
  }

  //代碼層接管RN的物理返回鍵,
  //return true不做RN層的返回處理
  //交由Native層處理ActivityResult
  _onBackAndroid = () => {
    NativeModules.MyNativeBridgeModule.finishActivityForResult("回傳onActivityResult值1");
    return true;
  }

  componentDidMount() {
    //調用原生方法,獲取Activity的Intent數據
    NativeModules.MyNativeBridgeModule.getDataFromIntent(
      (result) => {
        //獲取了回調結果,并修改了state的title
        this.setState({
          intentData:result,
        })
      },
      (error) => {
        console.log(error);
      }
    );

    //注冊Android物理返回鍵監聽
    BackHandler.addEventListener('hardwareBackPress', this._onBackAndroid);

     //注冊通知
    this.subscription = DeviceEventEmitter.addListener('notify',(result)=>{
      NativeModules.MyNativeBridgeModule.showToast(result,NativeModules.MyNativeBridgeModule.Duration_Short);
    });
  }

  componentWillUnmount() {
    //解綁Android物理返回鍵監聽
    BackHandler.removeEventListener('hardwareBackPress', this._onBackAndroid);
    // 移除通知
    this.subscription.remove();
  }

  //調用原生方法,打開新的Activity,并可傳遞數據
  _startNewActivity = ()=>{
    NativeModules.MyNativeBridgeModule.startNewActivityByString("","",(result)=>{
      NativeModules.MyNativeBridgeModule.showToast(result,NativeModules.MyNativeBridgeModule.Duration_Short);
    });
  }

  render() {
    //獲取原生常量值
    const Native_Constants_A = NativeModules.MyNativeBridgeModule.Native_Constants_A;
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          {this.state.title}
        </Text>
        <Text style={styles.instructions}>
          {this.state.intentData}
        </Text>
        <Text style={styles.instructions}>
          {Native_Constants_A}
        </Text>
        <TouchableOpacity onPress={this._showToast} style={styles.button}>
          <Text style={styles.instructions}>
            點我調用原生Toast
          </Text>
        </TouchableOpacity>
        <TouchableOpacity onPress={this._testCallback} style={styles.button}>
          <Text style={styles.instructions}>
            點我調用原生方法并獲取回調結果
          </Text>
        </TouchableOpacity>
        <TouchableOpacity onPress={this._startNewActivity} style={styles.button}>
          <Text style={styles.instructions}>
            點我打開原生Activity(RN->Native)
          </Text>
        </TouchableOpacity>
      </View>
    );
  }
}
//暴露給原生使用
AppRegistry.registerComponent('FirstReactComponent', () => FirstReactComponent);

3)訪問原生側常量

在自定義的原生模塊中,通過重寫getConstants()即可被RN訪問常量。
RN通過NativeModules.MyNativeBridgeModule.Native_Constants_A;即可調用。
~/MyNativeBridgeModule.java

    //此方法可被RN端訪問常量
    @Nullable
    @Override
    public Map<String, Object> getConstants() {
        final Map<String, Object> constants = new HashMap<String, Object>();
        constants.put("Duration_Short", Toast.LENGTH_SHORT);
        constants.put("Duration_Long", Toast.LENGTH_LONG);
        constants.put("Native_Constants_A", "我是Native常量值");
        return constants;
    }

~/FirstReactComponent.js

NativeModules.MyNativeBridgeModule.Native_Constants_A;

4)訪問原生側方法

原生通過注解 @ReactMethod暴露

4.1)void無返回

    //@ReactMethod 此注解定義與RN端的調用方法
    @ReactMethod
    public void showToast(String msg, int duration) {
        Toast.makeText(getReactApplicationContext(), msg, duration).show();
    }
  //調用原生方法 showToast
  _showToast = ()=>{
    NativeModules.MyNativeBridgeModule.showToast('調用原生Toast',NativeModules.MyNativeBridgeModule.Duration_Short);
  }

4.2)有返回回調

由于跨端的訪問都是異步進行,可以通過Callback回調函數獲取返回值

    //方法的返回類型必須為void,跨端訪問為異步進行,需要返回值須寫回調
    @ReactMethod
    public void testCallBack(String msg, Callback successCB, Callback errorCB) {
        try {
            String result = msg + " ,但我被testCallBack方法修改了";
            successCB.invoke(result);
        } catch (Exception e) {
            errorCB.invoke("異常:" + e.getMessage());
        }
    }
  //調用原生方法 并獲取回調結果
  _testCallback = ()=>{
    NativeModules.MyNativeBridgeModule.testCallBack(this.state.title,
      (result)=>{
        console.log(result);
        //獲取了回調結果,并修改了state的title
        this.setState({
          title:result,
        })
      },
      (error)=>{
        console.log(error);
      }
    );
  }

5)原生啟動RN

Intent intent = new Intent(this,FirstReactActivity.class);
intent.putExtra("intentData","我是MainActivity傳遞的intentData");
startActivityForResult(intent,1001);

5.1)RN獲取Activity傳遞的Intent數據

    //實例:原生->RN 獲取之前Activity傳遞的數據
    @ReactMethod
    public void getDataFromIntent(Callback successCB, Callback errorCB) {
        try {
            Activity currentActivity = getCurrentActivity();
            String intentString = currentActivity.getIntent().getStringExtra("intentData");
            successCB.invoke(intentString);
        } catch (Exception e) {
            errorCB.invoke("異常:" + e.getMessage());
        }
    }
componentDidMount() {
    //調用原生方法,獲取Activity的Intent數據
    NativeModules.MyNativeBridgeModule.getDataFromIntent(
      (result) => {
        //獲取了回調結果,并修改了state的title
        this.setState({
          intentData:result,
        })
      },
      (error) => {
        console.log(error);
      }
    );
}

5.2)startActivityForResult返回Intent數據給Activity

    //實例:原生->RN  startActivityForResult 返回數據給之前的Activity
    @ReactMethod
    public void finishActivityForResult(String msg) {
        Activity currentActivity = getCurrentActivity();
        Intent intent = new Intent();
        intent.putExtra("intentData", msg);
        currentActivity.setResult(Activity.RESULT_OK, intent);
        currentActivity.finish();
    }

通過接管返回操作來優先調用@ReactMethod方法。若在componentWillUnmount()中處理會導致Activity優先接收到onActivityResult,而后進入@ReactMethod方法。

//代碼層接管RN的物理返回鍵,
//return true不做RN層的返回處理
//交由Native層處理ActivityResult
_onBackAndroid = () => {
     NativeModules.MyNativeBridgeModule.finishActivityForResult("回傳onActivityResult值1");
     return true;
}

componentDidMount() {
  //注冊Android物理返回鍵監聽
  BackHandler.addEventListener('hardwareBackPress', this._onBackAndroid);
}
componentWillUnmount() {
  //解綁Android物理返回鍵監聽
  BackHandler.removeEventListener('hardwareBackPress', this._onBackAndroid);
}

6)RN啟動原生

RN啟動原生可采用隱式或顯示(須反射)啟動

6.1)Activity獲取RN傳遞的Intent數據

    //實例: RN->原生  打開新的Activity
    //實際項目中可進行實際封裝
    @ReactMethod
    public void startNewActivityByString(String activityName, String data, Callback resultCB) {
        Activity currentActivity = getCurrentActivity();
        //此處采用隱式啟動,方便封裝。若顯示啟動,需要反射獲取class,或業務層上做kv映射。
        Intent intent = new Intent("com.tgf.studyrn_native_android.SecondActivity");
        //此處采用顯示啟動,需要反射
//        Class aimActivity = null;
//        try {
//            aimActivity = Class.forName("com.tgf.studyrn_native_android.SecondActivity");
//        } catch (ClassNotFoundException e) {
//            e.printStackTrace();
//        }
//        Intent intent = new Intent(currentActivity,aimActivity);

        //將回調函數賦值給全局變量,以便全局callback在mActivityEventListener中使用
        secondActivityOnActivityResultCallback = resultCB;
        currentActivity.startActivityForResult(intent, 1002);
    }
  //調用原生方法,打開新的Activity,并可傳遞數據
  _startNewActivity = ()=>{
    NativeModules.MyNativeBridgeModule.startNewActivityByString("","",(result)=>{
      NativeModules.MyNativeBridgeModule.showToast(result,NativeModules.MyNativeBridgeModule.Duration_Short);
    });
  }

6.2)startActivityForResult返回Intent數據給RN

須定義監聽BaseActivityEventListener,通過其onActivityResult來獲取。
方式一:全局變量secondActivityOnActivityResultCallback發出回調給RN
方式二:rnContext.getJSModule發出通知給RN

//定義全局回調,RN->原生  startActivityForResult 返回數據給之前的 RNActivity
private Callback secondActivityOnActivityResultCallback;

//定義全局rnContext
private ReactApplicationContext rnContext;

public MyNativeBridgeModule(ReactApplicationContext reactContext) {
  super(reactContext);
  rnContext = reactContext;
  //定義監聽 RN->原生  startActivityForResult 返回數據給之前的 RNActivity
  reactContext.addActivityEventListener(mActivityEventListener);
}
//實例:RN->原生  startActivityForResult 返回數據給之前的 RNActivity
//方式一 : Callback回調
//方式二 : 發送通知
private final ActivityEventListener mActivityEventListener = new BaseActivityEventListener() {
  @Override
  public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent intent) {
    switch (requestCode) {
      case 1002:
  //方式一 : Callback回調
      //try {
      //secondActivityOnActivityResultCallback.invoke(intent.getStringExtra("intentData"));
      //}catch (Exception e){
      //}

  //方式二 : 發送通知
        rnContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("notify", intent.getStringExtra("intentData"));
        break;
    }
  }
};

6.3)原生發送通知給RN

發送部分參見6.2

  componentDidMount() {
     //注冊通知
    this.subscription = DeviceEventEmitter.addListener('notify',(result)=>{
      NativeModules.MyNativeBridgeModule.showToast(result,NativeModules.MyNativeBridgeModule.Duration_Short);
    });
  }

  componentWillUnmount() {
    // 移除通知
    this.subscription.remove();
  }

7)UI互嵌

7.1)原生界面內部分使用RN的界面

原生界面內部分使用RN的界面

*實例:在原生Activity中部分使用RN的UI,應將Rn的組件作為Android中的fragment來使用

  • 新建MyReactFragment繼承Fragment
public abstract class MyReactFragment extends Fragment {
    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;

    //返回RN 的 Appregistry注冊的組件名字.
    public abstract String getMainComponentName();

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mReactRootView = new ReactRootView(context);
        mReactInstanceManager =
                ((MainApplication) getActivity().getApplication())
                        .getReactNativeHost()
                        .getReactInstanceManager();
    }

    //這里改寫根View為ReactRootView,因此繼承此類的fragment實現`getMainComponentName`即可
    @Override
    public ReactRootView onCreateView(LayoutInflater inflater, ViewGroup group, Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        return mReactRootView;
    }


    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mReactRootView.startReactApplication(
                mReactInstanceManager,
                getMainComponentName(),
                null
        );
    }
}
  • 新建ThirdReactFragment繼承第一步創建的MyReactFragment
public class ThirdReactFragment extends MyReactFragment {
    @Override
    public String getMainComponentName() {
        //對應RN 的 Appregistry注冊的組件名字.
        return "ThirdReactComponent";
    }
}
  • RN側創建ThirdReactComponent組件給原生側使用
export default class ThirdReactComponent extends Component {
    //調用原生方法 showToast
    _showToast = ()=>{
        NativeModules.MyNativeBridgeModule.showToast('調用原生Toast',NativeModules.MyNativeBridgeModule.Duration_Short);
    }

    render() {
        return (
        <View style={styles.container}>
            <TouchableOpacity onPress={this._showToast}>
            <Text>大家好 我是React的UI,我準備嵌入到原生UI里</Text>
            </TouchableOpacity>
        </View>
        );
    }
}
//暴露給原生使用
AppRegistry.registerComponent('ThirdReactComponent', () => ThirdReactComponent);
  • Android創建Activity
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.tgf.studyrn_native_android.SecondActivity">
    
    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="100dp"></FrameLayout>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="40dp"
        android:layout_centerInParent="true"
        android:text="大家好,我是原生SecondActivity"/>
</LinearLayout>
public class SecondActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {

    private ReactInstanceManager mReactInstanceManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        mReactInstanceManager =
                ((MainApplication) getApplication()).getReactNativeHost().getReactInstanceManager();
        Fragment viewFragment = new ThirdReactFragment();
        getSupportFragmentManager().beginTransaction().add(R.id.container,viewFragment).commit();
    }

    //掛載的Activity還需要實現DefaultHardwareBackBtnHandler接口,以保證RN的生命周期=========
    @Override
    public void invokeDefaultOnBackPressed() {
        super.onBackPressed();
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostPause();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostResume(this, this);
        }
    }
}

7.2)RN界面內部分使用原生的界面

RN界面內部分使用原生的界面

*示例:在RN的界面中部分使用原生的TextView組件。

  • 創建一個視圖管理類MyTextViewManager
public class MyTextViewManager extends SimpleViewManager<ReactTextView> {

    @Override
    public String getName() {
        //方法返回的名字會用于在JavaScript端引用這個原生視圖
        return "MyTextViewManager";
    }

    @Override
    protected ReactTextView createViewInstance(ThemedReactContext reactContext) {
        ReactTextView textView = new ReactTextView(reactContext);
        return textView;
    }

    //@ReactProp
    //(name = "text")  這個參數指定了對應屬性在JavaScript端的名字
    @ReactProp(name = "text")
    public void setText(ReactTextView textView,String text){
        textView.setText(text);
    }
}
  • 在MyReactPackage注冊第一步新建的ViewManager
    ~/MyReactPackage.java
@Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        List<ViewManager> modules = new ArrayList<>();
        modules.add(new MyTextViewManager()); //注冊自定義的ViewManager模塊
        return modules;
    }
  • 實現對應的JavaScript模塊
import { PropTypes } from 'react';
import { requireNativeComponent, View } from 'react-native';

var myTextView = {
  name: 'MyTextView',
  propTypes: {
    text:PropTypes.string,
    ...View.propTypes //包含默認的View的屬性,如果沒有這句會報‘has no propType for native prop’錯誤
  },
};

module.exports = requireNativeComponent('MyTextViewManager', myTextView);
  • 在Rn組件中引用此JS模塊
import MyTextView from './MyTextView';
export default class SecondReactComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      title:'大家好,我是SecondReactComponent界面',
    };
  }

  render() {
    return (
      <View style={styles.container}>
        <MyTextView
            style={styles.welcome}
            text={'大家好,我使用了原生自定義的MyTextView組件'}/>
        <Text>{this.state.title}</Text>
      </View>
    );
  }
}
//暴露給原生使用
AppRegistry.registerComponent('SecondReactComponent', () => SecondReactComponent);
  • 新建SecondReactActivity繼承ReactActivity
public class SecondReactActivity extends ReactActivity {

    @Override
    protected String getMainComponentName() {
        return "SecondReactComponent";  //注冊的react組件名,一會在JS里要用到
    }
}

參考資料

官網
https://github.com/ipk2015/RN-Resource-ipk/tree/master/react-native-docs


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,698評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,202評論 3 426
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,742評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,580評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,297評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,688評論 1 327
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,693評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,875評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,438評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,183評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,384評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,931評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,612評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,022評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,297評論 1 292
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,093評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,330評論 2 377

推薦閱讀更多精彩內容