在 Fragment 中使用 React Native

React Native 官网提供了在 Activity 中使用 React Native 的方法,最近项目中需要在 Fragment 中使用 React Native,参考

React Native 官网提供了在 Activity 中使用 React Native 的方法,最近项目中需要在 Fragment 中使用 React Native,参考 http://stackoverflow.com/questions/35221447/react-native-inside-a-fragment

及各种尝试摸索后总结方法如下。

1. MyApplication

MyApplication

除了实现 ReactApplication

的抽象方法 getReactNativeHost

外,还需要获取到 ReactContext

并提供 get

接口,因为在 Fragment

里无法获取到 ReactContext

,只能获取 Context

,而原生调用 js 时使用 sendEvent

又需要用到 ReactContext

Fragment 中通过 ReactInstanceManager#getCurrentReactContext

获取到的 ReactContext

为空。

publicclassMyApplicationimplementsReactApplication{

// ...

privateReactContext mReactContext;

publicReactContextgetReactContext(){

returnmReactContext;

}

privatefinalReactNativeHost mReactNativeHost =newReactNativeHost(this) {

@Override

protectedbooleangetUseDeveloperSupport(){

returnBuildConfig.DEBUG;

}

@Override

protectedList<ReactPackage>getPackages(){

returnArrays.<ReactPackage>asList(

newMainReactPackage(),

newMyReactPackage(),

newOtherReactPackage()

// ...

);

}

};

@Override

publicReactNativeHostgetReactNativeHost(){

returnmReactNativeHost;

}

privatevoidregisterReactInstanceEventListener(){

mReactNativeHost.getReactInstanceManager().addReactInstanceEventListener(mReactInstanceEventListener);

}

privatevoidunRegisterReactInstanceEventListener(){

mReactNativeHost.getReactInstanceManager().removeReactInstanceEventListener(mReactInstanceEventListener);

}

privatefinalReactInstanceManager.ReactInstanceEventListener mReactInstanceEventListener =newReactInstanceManager.ReactInstanceEventListener() {

@Override

publicvoidonReactContextInitialized(ReactContext context){

mReactContext = context;

}

};

@Override

publicvoidonCreate(){

// ...

registerReactInstanceEventListener();

}

}

Application

onCreate

方法里注册一个 ReactInstanceEventListener

,用于初始化后获取到 ReactContext

2. ReactInstanceManager

通过 ReactNativeHost#getReactInstanceManager

可以获取 ReactInstanceManager

这个抽象类,它提供了 ReactInstanceEventListener

接口及相应的添加和删除方法。

/**

* Add a listener to be notified of react instance events.

*/

publicabstractvoidaddReactInstanceEventListener(ReactInstanceEventListener listener);

/**

* Remove a listener previously added with {@link#addReactInstanceEventListener}.

*/

publicabstractvoidremoveReactInstanceEventListener(ReactInstanceEventListener listener);

/**

* Listener interface for react instance events.

*/

publicinterfaceReactInstanceEventListener{

/**

* Called when the react context is initialized (all modules registered). Always called on the

* UI thread.

*/

voidonReactContextInitialized(ReactContext context);

}

3. BaseReactFragment

BaseReactFragment

继承自自己封装的 Fragment

基类 BaseFragment

,这里需要用到 ReactRootView

ReactInstanceManager

它们在 Fragment

onAttach

方法中获取,并在 onCreateView

方法中返回该 ReactRootView

onActivityCreated

方法中即可使用我们的 React Native 组件,这里需要子类实现 getMainPageName

抽象方法,获取到对应的 React Native 组件。

publicabstractclassBaseReactFragmentextendsBaseFragment{

privateReactRootView mReactRootView;

privateReactInstanceManager mReactInstanceManager;

@Override

publicvoidonAttach(Activity activity){

super.onAttach(activity);

mReactRootView = newReactRootView(activity);

mReactInstanceManager = ((MyApplication) getActivity().getApplication()).getReactNativeHost().getReactInstanceManager();

}

@Nullable

@Override

publicViewonCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState){

super.onCreateView(inflater, container, savedInstanceState);

returnmReactRootView;

}

@Override

publicvoidonViewCreated(View view, Bundle savedInstanceState){

}

@Override

publicvoidonActivityCreated(@Nullable Bundle savedInstanceState){

super.onActivityCreated(savedInstanceState);

mReactRootView.startReactApplication(mReactInstanceManager, getMainPageName(), null);

}

protectedabstractStringgetMainPageName();

protectedvoidsendEvent(String eventName,

@Nullable WritableMap params) {

if(((MyApplication) getActivity().getApplication()).getReactContext() !=null) {

((MyApplication) getActivity().getApplication()).getReactContext()

.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)

.emit(eventName, params);

}

}

}

sendEvent

方法用于原生调用 js 的接口,需要获取到 ReactContext

对象,通过 ReactInstanceManager#getCurrentReactContext

获取到的 ReactContext

为空,这里从 Application

中获取。

创建一个 BaseReactFragment

的子类用于装载 React Native 组件

publicclassMyFragmentextendsBaseReactFragment{

@Override

publicStringgetMainPageName(){

return"MyComponent";// name of our React Native component we've registered

}

}

4. BaseReactActivity

BaseReactFragment

所在的 Activity

必须实现 DefaultHardwareBackBtnHandler

,用于绑定 React Native 组件的生命周期。

publicclassBaseReactActivityextendsBaseActivityimplementsDefaultHardwareBackBtnHandler{

/*

* Get the ReactInstanceManager, AKA the bridge between JS and Android

* We use a singleton here so we can reuse the instance throughout our app

* instead of constantly re-instantiating and re-downloading the bundle

*/

privateReactInstanceManager mReactInstanceManager;

@Override

protectedvoidonCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

/**

* Get the reference to the ReactInstanceManager

*/

mReactInstanceManager =

((MyApplication) getActivity().getApplication()).getReactNativeHost().getReactInstanceManager();

}

@Override

publicvoidinvokeDefaultOnBackPressed(){

super.onBackPressed();

}

/*

* Any activity that uses the ReactFragment or ReactActivty

* Needs to call onHostPause() on the ReactInstanceManager

*/

@Override

protectedvoidonPause(){

super.onPause();

if(mReactInstanceManager !=null) {

mReactInstanceManager.onHostPause();

}

}

/*

* Same as onPause - need to call onHostResume

* on our ReactInstanceManager

*/

@Override

protectedvoidonResume(){

super.onResume();

if(mReactInstanceManager !=null) {

mReactInstanceManager.onHostResume(this,this);

}

}

}

未登录用户
全部评论0
到底啦