怎么实现预加载来解决白屏问题呢

来源:16-10 React Native 混合开发实战(iOS篇)-1【解锁新的开发方式】

慕粉1509133595

2020-07-29

想问一下老师,Android原生加载RN页面,怎么实现预加载来解决白屏问题呢

写回答

1回答

CrazyCodeBoy

2020-07-30

可以参考下咱们体系课https://class.m.imooc.com/sale/mobilearchitect中关于预加载和缓存的实现思路:

package org.devio.`as`.proj.common.rn

import android.app.Activity
import android.os.Bundle
import android.os.Looper
import android.view.ViewGroup
import com.facebook.react.ReactInstanceManager
import com.facebook.react.ReactRootView
import com.facebook.react.common.LifecycleState
import com.facebook.react.shell.MainReactPackage
import org.devio.`as`.proj.common.BuildConfig
import java.util.*

/**
 * RN优化提升加载速度,实现秒卡RN模块
 * 0.如何让预加载不损失"首页"性能
 * 1.预加载日和不让RN其控制activity,比如修改activity状态栏
 * 2.如何让RN获取到真实的Activity而不是预加载时的Activity
 * 3.如何在当第二次获取RN缓存时不出现空白页
 */
class HiRNCacheManager private constructor() {
    /**
     * 预加载RN
     */
    fun preLoad(
        activity: Activity,
        moduleName: String,
        initPrams: Bundle
    ) {
        //在线程空闲时执行预加载任务
        Looper.myQueue().addIdleHandler {
            val reactRootView = initReactRootView(activity, moduleName, initPrams)
            if (reactRootView.reactInstanceManager != null) {
                //预加载时,不让其控制activity,比如修改activity状态栏
                reactRootView.reactInstanceManager!!.onHostDestroy(activity)
            }
            CACHED_VIEW[moduleName] = reactRootView
            false
        }
    }

    /**
     * 获取预加载的RN
     */
    fun getCachedReactRootView(
        activity: Activity,
        moduleName: String,
        initPrams: Bundle
    ): ReactRootView? {
        var reactRootView = CACHED_VIEW[moduleName]
        if (reactRootView == null) {
            reactRootView = initReactRootView(activity, moduleName, initPrams)
        }
        if (reactRootView.reactInstanceManager != null) {
            //替换预加载的activity
            reactRootView.reactInstanceManager!!.onHostResume(activity)
            reactRootView.reactInstanceManager!!.onHostDestroy(activity)
            reactRootView.reactInstanceManager!!.onHostResume(activity)
        }
        detachRootView(moduleName)
        return reactRootView
    }

    /**
     * 初始化RN
     */
    private fun initReactRootView(
        activity: Activity,
        moduleName: String,
        initPrams: Bundle
    ): ReactRootView {
        val reactRootView = ReactRootView(activity)
        val reactInstanceManager = ReactInstanceManager.builder()
            .setApplication(activity.application)
            .setCurrentActivity(activity)
            .setBundleAssetName("index.android.bundle")
            .setJSMainModulePath("index")
            .addPackage(MainReactPackage()) //注册自定义插件
            .addPackage(HiReactPackage())
            .setUseDeveloperSupport(BuildConfig.DEBUG)
            .setInitialLifecycleState(LifecycleState.RESUMED)
            .build()
        //和index.js中AppRegistry.registerComponent()注册的module保持对应
        reactRootView.startReactApplication(reactInstanceManager, moduleName, initPrams)
        return reactRootView
    }

    /**
     * 从父容器中移除RN
     */
    fun detachRootView(component: String) {
        val rootView = CACHED_VIEW[component] ?: return
        val parent = rootView.parent as? ViewGroup
        parent?.removeView(rootView)
    }

    companion object {
        @JvmStatic
        @get:Synchronized
        var instance: HiRNCacheManager? = null
            get() {
                if (field == null) {
                    field = HiRNCacheManager()
                }
                return field
            }
            private set
        private val CACHED_VIEW: MutableMap<String, ReactRootView> =
            HashMap()

    }
}


1
0

RN入门到进阶,打造高质量上线App

解锁React Native开发应用新姿势,React Native新版本热门技术

3144 学习 · 3241 问题

查看课程