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