React Native基于最新版本实现JsBundle预加载,界面秒开优化功能

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


刚创建的React Native 微信公众号,欢迎微信扫描关注订阅号,每天定期会分享react native 技术文章,移动技术干货,精彩文章技术推送。同时可以扫描我的微信加入react-native技术交流微信群。欢迎各位大牛,React Native技术爱好者加入交流!




一、需求分析


前几篇博客中,和大家分享了关于React Native For Android 的一系列内容,以及React Native第三方库的使用技巧。今天和大家分享的内容可以算是React Native基于最新版本实现JsBundle预加载,界面秒开优化功能延伸。

本篇博客围绕的依然是如何加载RN界面,在JsBundle加载优化这篇博客中,我们从源码角度分析了如何实现快速加载RN界面,RN界面的加载在ReactActivity的onCreate中完成,实则是通过ReactDelegate委托类的onCreate来实现。在ReactDelegate的onCreate方法中,系统调用loadApp来加载RN根视图,在loadApp方法中通过createRootView创建视图(new ReactRootView()),并启动设置到Activity的ContentView(DecoerView)上。


二、视图加载


React Native基于最新版本实现JsBundle预加载,界面秒开优化博客中,我们介绍到了如何去预先加载ReactRootView。

        ReactRootView rootView = new ReactRootView(activity);  
        rootView.startReactApplication(  
                ((ReactApplication) activity.getApplication()).getReactNativeHost().getReactInstanceManager(),  
                componentName,  
                null);  

此时当我们加载出ReactRootView后,就可以将其添加到我们Activity或者Fragment布局。但是此时会发现一个问题,如果RN中视图控件有交互功能,例如单击事件,此时这些功能都失效了。百思不得姐后,查看源码会发现交互的功能都由ReactDelegate来实现,所以我们单纯加载ReactRootView只是显示了视图,但是交互是不行的。如何解决呢?


三、功能实现


上面我们分析了整个RN视图加载的流程,那么如何在现有Activity布局中加载RN界面呢?原理依然要从创建设置ReactRootView来解决。RN的新版本对设置创建ReactRootView进行了封装,使得我们只需要重写getMainComponentName方法返回RN注册名称即可。这就使得我们不能直接控制ReactRootView的创建和设置。所以依然要采用重写ReactDelegate的方式来解决。

    public class MyReactDelegate {  
      
        private final Activity mActivity;  
        private ReactRootView mReactRootView;  
        private Callback mPermissionsCallback;  
        private final String mMainComponentName;  
        private PermissionListener mPermissionListener;  
        private final int REQUEST_OVERLAY_PERMISSION_CODE = 1111;  
        private DoubleTapReloadRecognizer mDoubleTapReloadRecognizer;  
      
        public PreLoadReactDelegate(Activity activity, @Nullable String mainComponentName) {  
            this.mActivity = activity;  
            this.mMainComponentName = mainComponentName;  
        }  
      
        public void onCreate() {  
            boolean needsOverlayPermission = false;  
            if (getReactNativeHost().getUseDeveloperSupport() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {  
                // Get permission to show redbox in dev builds.  
                if (!Settings.canDrawOverlays(mActivity)) {  
                    needsOverlayPermission = true;  
                    Intent serviceIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + mActivity.getPackageName()));  
                    mActivity.startActivityForResult(serviceIntent, REQUEST_OVERLAY_PERMISSION_CODE);  
                }  
            }  
      
            if (mMainComponentName != null && !needsOverlayPermission) {  

                  mReactRootView = new ReactRootView(mActivity);  
                  mReactRootView.startReactApplication(  
                            getReactInstanceManager(),  
                            mMainComponentName,  
                            null);  
                }  
                // 3.将RootView设置到Activity布局
          mActivity.setContentView(R.layout.acty_rn);
          ((FrameLayout)mActivity.findViewById(R.id.rn_contaner)).addView(mReactRootView);
            }  
      
            mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();  
        }  
      
        public void onResume() {  
            if (getReactNativeHost().hasInstance()) {  
                getReactInstanceManager().onHostResume(mActivity, (DefaultHardwareBackBtnHandler)mActivity);  
            }  
            if (mPermissionsCallback != null) {  
                mPermissionsCallback.invoke();  
                mPermissionsCallback = null;  
            }  
        }  
      
        public void onPause() {  
            if (getReactNativeHost().hasInstance()) {  
                getReactInstanceManager().onHostPause(mActivity);  
            }  
        }  
      
        public void onDestroy() {  
      
            if (mReactRootView != null) {  
                mReactRootView.unmountReactApplication();  
                mReactRootView = null;  
            }  
            if (getReactNativeHost().hasInstance()) {  
                getReactInstanceManager().onHostDestroy(mActivity);  
            }  
      
            
        }  
      
        public boolean onNewIntent(Intent intent) {  
            if (getReactNativeHost().hasInstance()) {  
                getReactInstanceManager().onNewIntent(intent);  
                return true;  
            }  
            return false;  
        }  
      
        public void onActivityResult(int requestCode, int resultCode, Intent data) {  
            if (getReactNativeHost().hasInstance()) {  
                getReactInstanceManager().onActivityResult(mActivity, requestCode, resultCode, data);  
            } else {  
                // Did we request overlay permissions?  
                if (requestCode == REQUEST_OVERLAY_PERMISSION_CODE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {  
                    if (Settings.canDrawOverlays(mActivity)) {  
                        if (mMainComponentName != null) {  
                            if (mReactRootView != null) {  
                                throw new IllegalStateException("Cannot loadApp while app is already running.");  
                            }  
                            mReactRootView = new ReactRootView(mActivity);  
                            mReactRootView.startReactApplication(  
                                    getReactInstanceManager(),  
                                    mMainComponentName,  
                                    null);  
                            mActivity.setContentView(mReactRootView);  
                        }  
                    }  
                }  
            }  
        }  
      
        public boolean onBackPressed() {  
            if (getReactNativeHost().hasInstance()) {  
                getReactInstanceManager().onBackPressed();  
                return true;  
            }  
            return false;  
        }  
      
        public boolean onRNKeyUp(int keyCode) {  
            if (getReactNativeHost().hasInstance() && getReactNativeHost().getUseDeveloperSupport()) {  
                if (keyCode == KeyEvent.KEYCODE_MENU) {  
                    getReactInstanceManager().showDevOptionsDialog();  
                    return true;  
                }  
                boolean didDoubleTapR = Assertions.assertNotNull(mDoubleTapReloadRecognizer)  
                        .didDoubleTapR(keyCode, mActivity.getCurrentFocus());  
                if (didDoubleTapR) {  
                    getReactInstanceManager().getDevSupportManager().handleReloadJS();  
                    return true;  
                }  
            }  
            return false;  
        }  
      
        public void requestPermissions(String[] permissions, int requestCode, PermissionListener listener) {  
            mPermissionListener = listener;  
            mActivity.requestPermissions(permissions, requestCode);  
        }  
      
        public void onRequestPermissionsResult(final int requestCode, final String[] permissions, final int[] grantResults) {  
            mPermissionsCallback = new Callback() {  
                @Override  
                public void invoke(Object... args) {  
                    if (mPermissionListener != null && mPermissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {  
                        mPermissionListener = null;  
                    }  
                }  
            };  
        }  
      
        /** 
         * 获取 Application中 ReactNativeHost 
         * @return 
         */  
        private ReactNativeHost getReactNativeHost() {  
            return MainApplication.getInstance().getReactNativeHost();  
        }  
      
        /** 
         * 获取 ReactInstanceManager 
         * @return 
         */  
        private ReactInstanceManager getReactInstanceManager() {  
            return getReactNativeHost().getReactInstanceManager();  
        }  
    }  

核心依然是修改了onCreate中方法,我们在设置根布局时,不是直接设置ReactRootView,而是加载我们自己的Activity布局,然后将RN布局作为子布局添加到Activity布局,这样就可以实现在现有Activity布局中嵌入RN布局了。



三、效果图


点击查看源码

猜你喜欢

转载自blog.csdn.net/u013718120/article/details/73985790