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阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341

推荐阅读更多精彩内容