前言:最近有点迷茫,学的东西太多,然后感觉有点力不从心,也不知道还能坚持多久这样写博客,不说了~~ 烦!! 撸一下代码平复下心情~

React Native中我们都知道,所有的view摆在一个activity中(原谅我只能用android为例子),然后原生android启动的时候,如果后台进程比较多,或者手机比较渣一点的话,多多少少都会看到一个短暂的白屏现象,然后当自己的activity切换到rnactivity的时候,由于要去加载bundler.js里面的内容,如果rn页面比较多的话,我们会看到一个很长的白屏现象,有童鞋要说了:“我们加一个进度条提示一下”,是的!! 你可以这样做,但你面对一群吊炸天的产品,你不得不去研究下该怎么做~~~

思路:
1、解决android启动白屏,通过设置rnactivity的主题;
2、解决react native启动白屏:
方案一:
提前把rootview创建出来,然后提前加载jsbundler文件(程序入口)
方案二:
提前把rootview创建出来,然后提前加载jsbundler文件,把rootview的现实设置成“隐藏”,在rn的第一个页面加载完后通知原生,原生拿到通知回调给rnactivity,然后显示出rootview。

方案一的做法大家可以参考中文网的这篇博客:
ReactNative安卓首屏白屏优化

说一下方案二,当我尝试了方案一的做法后,确实app加载到rnactivity的白屏问题有所缓解,但是问题来了,按照方案一的做法因为我的rootview创建是在Aactivity,的rootview的context是跟Aactivity绑定的,比如你需要在rn中用到modal组件(对话框),我们都知道modal在native渲染的时候会被当成dialog使用,但是我们的modal是放在rootview上面的,所以modal显示的时候,也就是跟Aactivity绑定的,而此时我们Aactivity已经被我们干掉了,所以就会报错!!! 不知道官网的这哥们是没遇到这问题咋样,反正方案一肯定是不行的,所以我们只能把rootview的创建放在rnactivity,有小伙伴有要问了,“那怎么做到预加载呢?”,好啦!! 接下来就直接上代码了~~

首先我们看到android里面react native加载耗时的操作:

我们的项目可能是这样的:

package com.scrolltabdemo;public class MainActivity extends ReactActivity {    /**     * Returns the name of the main component registered from JavaScript.     * This is used to schedule rendering of the component.     */    @Override    protected String getMainComponentName() {        return "ScrollTabDemo";    }}

可以发现就一个activity,然后我们走进ReactActivity:

/** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */package com.facebook.react;import javax.annotation.Nullable;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.KeyEvent;import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;import com.facebook.react.modules.core.PermissionAwareActivity;import com.facebook.react.modules.core.PermissionListener;/** * Base Activity for React Native applications. */public abstract class ReactActivity extends Activity    implements DefaultHardwareBackBtnHandler, PermissionAwareActivity {  private final ReactActivityDelegate mDelegate;  protected ReactActivity() {    mDelegate = createReactActivityDelegate();  }  /**   * Returns the name of the main component registered from JavaScript.   * This is used to schedule rendering of the component.   * e.g. "MoviesApp"   */  protected @Nullable String getMainComponentName() {    return null;  }  /**   * Called at construction time, override if you have a custom delegate implementation.   */  protected ReactActivityDelegate createReactActivityDelegate() {    return new ReactActivityDelegate(this, getMainComponentName());  }  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    mDelegate.onCreate(savedInstanceState);  }  @Override  protected void onPause() {    super.onPause();    mDelegate.onPause();  }  @Override  protected void onResume() {    super.onResume();    mDelegate.onResume();  }  @Override  protected void onDestroy() {    super.onDestroy();    mDelegate.onDestroy();  }  @Override  public void onActivityResult(int requestCode, int resultCode, Intent data) {    mDelegate.onActivityResult(requestCode, resultCode, data);  }  @Override  public boolean onKeyUp(int keyCode, KeyEvent event) {    return mDelegate.onKeyUp(keyCode, event) || super.onKeyUp(keyCode, event);  }  @Override  public void onBackPressed() {    if (!mDelegate.onBackPressed()) {      super.onBackPressed();    }  }  @Override  public void invokeDefaultOnBackPressed() {    super.onBackPressed();  }  @Override  public void onNewIntent(Intent intent) {    if (!mDelegate.onNewIntent(intent)) {      super.onNewIntent(intent);    }  }  @Override  public void requestPermissions(    String[] permissions,    int requestCode,    PermissionListener listener) {    mDelegate.requestPermissions(permissions, requestCode, listener);  }  @Override  public void onRequestPermissionsResult(    int requestCode,    String[] permissions,    int[] grantResults) {    mDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults);  }  protected final ReactNativeHost getReactNativeHost() {    return mDelegate.getReactNativeHost();  }  protected final ReactInstanceManager getReactInstanceManager() {    return mDelegate.getReactInstanceManager();  }  protected final void loadApp(String appKey) {    mDelegate.loadApp(appKey);  }}

把所有的操作都放在了ReactActivityDelegate这个代理类中,继续往下走:

// Copyright 2004-present Facebook. All Rights Reserved.package com.facebook.react;import android.annotation.TargetApi;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.net.Uri;import android.os.Build;import android.os.Bundle;import android.provider.Settings;import android.support.v4.app.FragmentActivity;import android.view.KeyEvent;import android.widget.Toast;import com.facebook.common.logging.FLog;import com.facebook.infer.annotation.Assertions;import com.facebook.react.bridge.Callback;import com.facebook.react.common.ReactConstants;import com.facebook.react.devsupport.DoubleTapReloadRecognizer;import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;import com.facebook.react.modules.core.PermissionListener;import javax.annotation.Nullable;/** * Delegate class for {@link ReactActivity} and {@link ReactFragmentActivity}. You can subclass this * to provide custom implementations for e.g. {@link #getReactNativeHost()}, if your Application * class doesn't implement {@link ReactApplication}. */public class ReactActivityDelegate {  private final int REQUEST_OVERLAY_PERMISSION_CODE = 1111;  private static final String REDBOX_PERMISSION_GRANTED_MESSAGE =    "Overlay permissions have been granted.";  private static final String REDBOX_PERMISSION_MESSAGE =    "Overlay permissions needs to be granted in order for react native apps to run in dev mode";  private final @Nullable Activity mActivity;  private final @Nullable FragmentActivity mFragmentActivity;  private final @Nullable String mMainComponentName;  private @Nullable ReactRootView mReactRootView;  private @Nullable DoubleTapReloadRecognizer mDoubleTapReloadRecognizer;  private @Nullable PermissionListener mPermissionListener;  private @Nullable Callback mPermissionsCallback;  public ReactActivityDelegate(Activity activity, @Nullable String mainComponentName) {    mActivity = activity;    mMainComponentName = mainComponentName;    mFragmentActivity = null;  }  public ReactActivityDelegate(    FragmentActivity fragmentActivity,    @Nullable String mainComponentName) {    mFragmentActivity = fragmentActivity;    mMainComponentName = mainComponentName;    mActivity = null;  }  protected @Nullable Bundle getLaunchOptions() {    return null;  }  protected ReactRootView createRootView() {    return new ReactRootView(getContext());  }  /**   * Get the {@link ReactNativeHost} used by this app. By default, assumes   * {@link Activity#getApplication()} is an instance of {@link ReactApplication} and calls   * {@link ReactApplication#getReactNativeHost()}. Override this method if your application class   * does not implement {@code ReactApplication} or you simply have a different mechanism for   * storing a {@code ReactNativeHost}, e.g. as a static field somewhere.   */  protected ReactNativeHost getReactNativeHost() {    return ((ReactApplication) getPlainActivity().getApplication()).getReactNativeHost();  }  public ReactInstanceManager getReactInstanceManager() {    return getReactNativeHost().getReactInstanceManager();  }  protected void onCreate(Bundle savedInstanceState) {    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(getContext())) {        needsOverlayPermission = true;        Intent serviceIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getContext().getPackageName()));        FLog.w(ReactConstants.TAG, REDBOX_PERMISSION_MESSAGE);        Toast.makeText(getContext(), REDBOX_PERMISSION_MESSAGE, Toast.LENGTH_LONG).show();        ((Activity) getContext()).startActivityForResult(serviceIntent, REQUEST_OVERLAY_PERMISSION_CODE);      }    }    if (mMainComponentName != null && !needsOverlayPermission) {      loadApp(mMainComponentName);    }    mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();  }  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);  }  protected void onPause() {    if (getReactNativeHost().hasInstance()) {      getReactNativeHost().getReactInstanceManager().onHostPause(getPlainActivity());    }  }  protected void onResume() {    if (getReactNativeHost().hasInstance()) {      getReactNativeHost().getReactInstanceManager().onHostResume(        getPlainActivity(),        (DefaultHardwareBackBtnHandler) getPlainActivity());    }    if (mPermissionsCallback != null) {      mPermissionsCallback.invoke();      mPermissionsCallback = null;    }  }  protected void onDestroy() {    if (mReactRootView != null) {      mReactRootView.unmountReactApplication();      mReactRootView = null;    }    if (getReactNativeHost().hasInstance()) {      getReactNativeHost().getReactInstanceManager().onHostDestroy(getPlainActivity());    }  }  public void onActivityResult(int requestCode, int resultCode, Intent data) {    if (getReactNativeHost().hasInstance()) {      getReactNativeHost().getReactInstanceManager()        .onActivityResult(getPlainActivity(), 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(getContext())) {          if (mMainComponentName != null) {            loadApp(mMainComponentName);          }          Toast.makeText(getContext(), REDBOX_PERMISSION_GRANTED_MESSAGE, Toast.LENGTH_LONG).show();        }      }    }  }  public boolean onKeyUp(int keyCode, KeyEvent event) {    if (getReactNativeHost().hasInstance() && getReactNativeHost().getUseDeveloperSupport()) {      if (keyCode == KeyEvent.KEYCODE_MENU) {        getReactNativeHost().getReactInstanceManager().showDevOptionsDialog();        return true;      }      boolean didDoubleTapR = Assertions.assertNotNull(mDoubleTapReloadRecognizer)        .didDoubleTapR(keyCode, getPlainActivity().getCurrentFocus());      if (didDoubleTapR) {        getReactNativeHost().getReactInstanceManager().getDevSupportManager().handleReloadJS();        return true;      }    }    return false;  }  public boolean onBackPressed() {    if (getReactNativeHost().hasInstance()) {      getReactNativeHost().getReactInstanceManager().onBackPressed();      return true;    }    return false;  }  public boolean onNewIntent(Intent intent) {    if (getReactNativeHost().hasInstance()) {      getReactNativeHost().getReactInstanceManager().onNewIntent(intent);      return true;    }    return false;  }  @TargetApi(Build.VERSION_CODES.M)  public void requestPermissions(    String[] permissions,    int requestCode,    PermissionListener listener) {    mPermissionListener = listener;    getPlainActivity().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;        }      }    };  }  private Context getContext() {    if (mActivity != null) {      return mActivity;    }    return Assertions.assertNotNull(mFragmentActivity);  }  private Activity getPlainActivity() {    return ((Activity) getContext());  }}

ReactActivityDelegate类中的东西比较多,我们就直接看到一个叫o nCreate的方法:

  protected void onCreate(Bundle savedInstanceState) {    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(getContext())) {        needsOverlayPermission = true;        Intent serviceIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getContext().getPackageName()));        FLog.w(ReactConstants.TAG, REDBOX_PERMISSION_MESSAGE);        Toast.makeText(getContext(), REDBOX_PERMISSION_MESSAGE, Toast.LENGTH_LONG).show();        ((Activity) getContext()).startActivityForResult(serviceIntent, REQUEST_OVERLAY_PERMISSION_CODE);      }    }    if (mMainComponentName != null && !needsOverlayPermission) {      loadApp(mMainComponentName);    }    mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();  }
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);  }

可看到这么两行代码:

 mReactRootView = createRootView();    mReactRootView.startReactApplication(      getReactNativeHost().getReactInstanceManager(),      appKey,      getLaunchOptions());

这就是比较耗时的操作了,mReactRootView.startReactApplication干了很多不可描述的东西,有兴趣的童鞋可以看看我之前写过的一篇文章:
React-Native 热更新尝试(Android)

好啦! 看到真凶后,我们就正法一下它,哈哈!! 说笑了~ 既然这两个方法很耗时,那我就等这两个方法都执行完毕后我再去setContentView,然后rn加载完毕页面后,我再去显示rootview。

首先我们拖一份ReactActivity的源码,然后叫ReactActivity2:

/** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * 

* This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */package com.scrolltabdemo;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.KeyEvent;import android.view.View;import com.facebook.react.ReactInstanceManager;import com.facebook.react.ReactNativeHost;import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;import com.facebook.react.modules.core.PermissionAwareActivity;import com.facebook.react.modules.core.PermissionListener;import javax.annotation.Nullable;/** * Base Activity for React Native applications. */public abstract class ReactActivity2 extends Activity implements DefaultHardwareBackBtnHandler, PermissionAwareActivity { private final ReactActivityDelegate mDelegate; protected ReactActivity2() { mDelegate = createReactActivityDelegate(); } /** * Returns the name of the main component registered from JavaScript. * This is used to schedule rendering of the component. * e.g. "MoviesApp" */ protected @Nullable String getMainComponentName() { return null; } /** * Called at construction time, override if you have a custom delegate implementation. */ protected ReactActivityDelegate createReactActivityDelegate() { return new ReactActivityDelegate(this, getMainComponentName()); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mDelegate.onCreate(savedInstanceState); } @Override protected void onPause() { super.onPause(); mDelegate.onPause(); } @Override protected void onResume() { super.onResume(); mDelegate.onResume(); } @Override protected void onDestroy() { super.onDestroy(); mDelegate.onDestroy(); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { mDelegate.onActivityResult(requestCode, resultCode, data); } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { return mDelegate.onKeyUp(keyCode, event) || super.onKeyUp(keyCode, event); } @Override public void onBackPressed() { if (!mDelegate.onBackPressed()) { super.onBackPressed(); } } @Override public void invokeDefaultOnBackPressed() { super.onBackPressed(); } @Override public void onNewIntent(Intent intent) { if (!mDelegate.onNewIntent(intent)) { super.onNewIntent(intent); } } @Override public void requestPermissions( String[] permissions, int requestCode, PermissionListener listener) { mDelegate.requestPermissions(permissions, requestCode, listener); } @Override public void onRequestPermissionsResult( int requestCode, String[] permissions, int[] grantResults) { mDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults); } protected final ReactNativeHost getReactNativeHost() { return mDelegate.getReactNativeHost(); } protected final ReactInstanceManager getReactInstanceManager() { return mDelegate.getReactInstanceManager(); } protected final void loadApp(String appKey) { mDelegate.loadApp(appKey); } public View getRootView() { return mDelegate.getRootView(); }}

什么都不需要动,然后把里面的ReactActivityDelegate换成我们自己的ReactActivityDelegate,于是我们继续copy一份ReactActivityDelegate的代码:

import javax.annotation.Nullable;.....    protected void onCreate(Bundle savedInstanceState) {        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(getContext())) {                needsOverlayPermission = true;                Intent serviceIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getContext().getPackageName()));                FLog.w(ReactConstants.TAG, REDBOX_PERMISSION_MESSAGE);                Toast.makeText(getContext(), REDBOX_PERMISSION_MESSAGE, Toast.LENGTH_LONG).show();                ((Activity) getContext()).startActivityForResult(serviceIntent, REQUEST_OVERLAY_PERMISSION_CODE);            }        }        if (mMainComponentName != null && !needsOverlayPermission) {            loadApp(mMainComponentName);        }        mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();    }    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);    }    public View getRootView() {        return mReactRootView;    }}

我们也什么都没动,就是加了一个方法:

 public View getRootView() {        return mReactRootView;    }

然后注释了一行代码:

//        getPlainActivity().setContentView(mReactRootView);

然后把我们的MainActivity改一下,让它继承我们的ReactActivity2:

package com.scrolltabdemo;public class MainActivity extends ReactActivity2 {    /**     * Returns the name of the main component registered from JavaScript.     * This is used to schedule rendering of the component.     */    @Override    protected String getMainComponentName() {        return "ScrollTabDemo";    }}

然后我们在我们的MainActivity中,停留三秒再展示我们的rootview:

package com.scrolltabdemo;import android.os.Bundle;import android.os.Handler;import android.view.View;public class MainActivity extends ReactActivity2 {    private View mRootView;    @Override    protected void onCreate(Bundle savedInstanceState) {        //初始化rnrootview        super.onCreate(savedInstanceState);        //获取rnrootview        mRootView = getRootView();        //模拟loadding图片        new Handler().postDelayed(new Runnable() {            @Override            public void run() {                setContentView(mRootView);            }        },3000);    }    /**     * Returns the name of the main component registered from JavaScript.     * This is used to schedule rendering of the component.     */    @Override    protected String getMainComponentName() {        return "ScrollTabDemo";    }}

我们运行我们的app:

可以看到,我们一进app是白页面,然后过了三秒显示了我们的rn页面,

我们把一进去白页面改成一张引导图片:

找到android的AndroidManifest.xml文件:

然后给MainAcitivty一个主题叫AppLaunchTheme:

    <application        android:name=".MainApplication"        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme">        <activity            android:name=".MainActivity"            android:configChanges="keyboard|keyboardHidden|orientation|screenSize"            android:label="@string/app_name"            android:theme="@style/AppLaunchTheme"            android:windowSoftInputMode="adjustResize">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            intent-filter>        activity>        <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />        <activity android:name=".TestActivity">        activity>    application>manifest>

然后我们在style.xml中创建主题:

<resources>        <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">        -- Customize your theme here. -->    style>        <style name="AppLaunchTheme" parent="AppTheme">        <item name="windowNoTitle">trueitem>        <item name="android:windowBackground">@mipmap/bg_launcher    style>resources>

背景为一张图片:

name="android:windowBackground">@mipmap/bg_launcheritem>

然后再次运行app:

可以看到,打开app先显示一张引导图片,然后三秒后显示rn页面,

好啦!! 写到这里小伙伴疑问了,那我怎么保证三秒后rn页面加载出来了呢? 是的! 这就是我们接下来需要解决的问题,

也就是我们现在在MainAcitivity中是延时了三秒模拟inittoken等一系列的操作,然后直接显示我们的rn页面,也就是rootview,我们需要的是在rn页面没加载出来的时候一直显示引导页面,那怎么做呢?我们怎么知道rn页面已经加载完毕了呢??

我们直接在rn页面的第一个页面的componentDidMount方法中通知原生页面告诉它我已经加载完毕了:

demo的第一个页面叫ScrollTabDemo.js:

export default class ScrollTabDemo extends Component {  componentDidMount() {    NativeModules.Notification.showContentView();  }      .....  }

可以看到我在rn页面中调了一个:

NativeModules.Notification.showContentView();

方法,搞过rn与native交互的童鞋都知道,这是调native的方法,我简单的说一下怎么实现Notification.showContentView():

首先创建一个module文件,我们这里叫NotificationModule.java:

    class NotificationModule extends ReactContextBaseJavaModule {        public NotificationModule(ReactApplicationContext reactContext) {            super(reactContext);        }        @Override        public String getName() {            return "Notification";        }        @ReactMethod        public void showContentView() {            getCurrentActivity().sendBroadcast(new Intent("com.demo.show"));        }    }

然后创建一个NotificationPackage文件把module加进来:

public class NotificationPackage implements ReactPackage {    @Override    public List createNativeModules(ReactApplicationContext reactContext) {        List modules = new ArrayList<>();        modules.add(new NotificationModule(reactContext));        return modules;    }    @Override    public List<Class<? extends JavaScriptModule>> createJSModules() {        return Collections.emptyList();    }    @Override    public List createViewManagers(ReactApplicationContext reactContext) {        return Collections.emptyList();    }}

最后吧package文件注册进rn:

package com.scrolltabdemo;import android.app.Application;import com.facebook.react.ReactApplication;import com.facebook.react.ReactNativeHost;import com.facebook.react.ReactPackage;import com.facebook.react.shell.MainReactPackage;import com.facebook.soloader.SoLoader;import java.util.Arrays;import java.util.List;public class MainApplication extends Application implements ReactApplication {    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {        @Override        public boolean getUseDeveloperSupport() {            return BuildConfig.DEBUG;        }        @Override        protected List getPackages() {            return Arrays.asList(                    new MainReactPackage(),                    new CustomerViewPackage(),                    new NotificationPackage()            );        }    };    @Override    public ReactNativeHost getReactNativeHost() {        return mReactNativeHost;    }    @Override    public void onCreate() {        super.onCreate();        SoLoader.init(this, /* native exopackage */ false);    }}

好啦!! 可以看到,我们rn页面调了native的:

 @ReactMethod        public void showContentView() {            getCurrentActivity().sendBroadcast(new Intent("com.demo.show"));        }

native的showContentView方法发了一个广播‘com.demo.show“通知MainActivity,MainActivity收到广播后显示出rooview:

package com.scrolltabdemo;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.os.Bundle;import android.os.Handler;import android.view.View;import android.widget.Toast;public class MainActivity extends ReactActivity2 {    private View mRootView;    @Override    protected void onCreate(Bundle savedInstanceState) {        //初始化rnrootview        super.onCreate(savedInstanceState);        //获取rnrootview        mRootView = getRootView();        //模拟loadding图片        new Handler().postDelayed(new Runnable() {            @Override            public void run() {                mRootView.setVisibility(View.INVISIBLE);                setContentView(mRootView);            }        },3000);        registerReceiver(new BroadcastReceiver() {            @Override            public void onReceive(Context context, Intent intent) {                mRootView.setVisibility(View.VISIBLE);                Toast.makeText(MainActivity.this, "显示页面了", Toast.LENGTH_SHORT).show();            }        }, new IntentFilter("com.demo.show"));    }    /**     * Returns the name of the main component registered from JavaScript.     * This is used to schedule rendering of the component.     */    @Override    protected String getMainComponentName() {        return "ScrollTabDemo";    }}

再次运行代码:

好啦!! 我们的android app启动白屏,然后react-native启动白屏已经被我们彻底解决了。

我们这样做有什么弊端呢? 那就是只是针对当前rn的版本,如果rn版本android的源码实现方式不一样的话,我们可能改的文件也可能不一样了,关键是要弄清楚实现的思路~~~

好啦!! 如果小伙伴有什么疑问的话,可以联系我~~

欢迎入群,欢迎交流

qq技术交流群链接:

更多相关文章

  1. 安全新手入坑——HTML标签
  2. Nginx系列教程(四)| 一文带你读懂Nginx的动静分离
  3. Android之——任意时刻从子线程切换到主线程的实现(插曲)
  4. Android事件分发机制学习笔记
  5. [置顶] Android6.0权限系统
  6. android onPause()和onStop()区别
  7. Android(安卓)WebView内容宽度自适应
  8. 使用HTML来生产Android界面
  9. Android开发之Serializable 和 Parcelable的区别(源代码分享)

随机推荐

  1. Android 基础面试题目
  2. 最全的Android项目结构以及功能
  3. Android去除EditText的聚焦Focuse
  4. Android(安卓)安卓微信分享
  5. Android ActionBar的源代码分析(二)
  6. Android活动Acitivity启动模式之singleTa
  7. Android 实现答题器功能(通过手势实现翻页
  8. android之Activity
  9. android自定义控件:可旋转View:可作为Image
  10. Android(安卓)DSL简介