效果图
这里的“时空”页面除了上面的tab栏,其余完全是RN写的,然后嵌入Fragment使用,刚开始接到这个需求的时候,心里十万个不情愿,由于之前项目里面都是在Activity里面使用,而且React Native并没有提供直接在Fragment使用的基类,那么我们要怎么实现呢?
思考
了解React Native基本原理,应该知道,React Native无非是把js文件解析出来,然后映射成Android原始的组件,然后加入到布局里面,只要明白这一点,那么我们模仿React Native中使用Activity加载RN的流程。
Activity加载View流程
我们在使用Activity加载RN的时候,需要让Activity继承ReactFragmentActivity(这是RN框架提供类,里面封装了加载RN相关逻辑),代码请自行查看,在Activity各个生命周期里委托给ReactActivityDelegate类。那接下来第一步就是模仿ReactFragmentActivity的实现。
- 模仿ReactFragmentActivity的实现
public abstract class BaseReactFragment extends Fragment implements PermissionAwareActivity { private ReactFragmentDelegate mDelegate; private Activity mActivity; ... protected ReactFragmentDelegate createReactFragmentDelegate() { return new ReactFragmentDelegate(this, getMainComponentName()); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mDelegate = createReactFragmentDelegate(); mActivity = getActivity(); mDelegate.onCreate(savedInstanceState); } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return mDelegate.onCreateView(inflater, container, savedInstanceState); } @Override public void onViewCreated(View view, @android.support.annotation.Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); } ... }
- 创建ReactActivityDelegate实例
需要传入两个参数,第一个就是当前“Activity”,第二个是个String对象,代表当前要加载的RN组件名。protected ReactActivityDelegate createReactActivityDelegate() { return new ReactActivityDelegate(this, getMainComponentName()); }
- onCreate生命周期重要函数
protected void loadApp(String appKey) { if (mReactRootView != null) { throw new IllegalStateException("Cannot loadApp while app is already running."); } mReactRootView = createRootView(); mReactRootView.startReactApplication( getReactNativeHost().getReactInstanceManager(), appKey, getLaunchOptions()); getPlainActivity().setContentView(mReactRootView); }
- 创建RN根View —— mReactRootView = createRootView()
- 调用ReactRootView的startReactApplication方法
- 调用getPlainActivity().setContentView(mReactRootView)
将创建好的ReactRootView 设置给Activity,这样Acitity显示的就是设置的View了,既然是这样,那么只要我们能拿到这个View对象,那么就可以做很多事情了。
- 创建ReactActivityDelegate实例
其它请自行查看源码,包括怎么获取参数,路径,在哪里把js解析成Android原生组件的。