feat(runtime): 新增 MultipleReactActivityDelegate 以支持分包加载- 添加 MultipleReactActivityDelegate 类,用于处理多个 React 活动

- 实现 ReactHostHelper 类,辅助加载bundle
- 修改 BuzActivity 和 MainApplication 以支持新的分包加载逻辑
- 更新 App.tsx,添加新功能按钮
- 在 package.json 中添加 --active-arch-only 参数以优化性能
- 在 gradle.properties 中启用配置缓存
这个提交包含在:
xuqm 2025-07-15 12:47:06 +08:00
父节点 dfa3180cec
当前提交 bf61fdc1ac
共有 15 个文件被更改,包括 243 次插入25 次删除

查看文件

@ -0,0 +1,4 @@
__d(function(g,r,i,a,m,e,d){var n=r(d[0]),p=r(d[1]),t=n(r(d[2]));p.AppRegistry.registerComponent(r(d[3]).Apps.App,function(){return t.default})},10000000,[5,3,10000001,491]);
__d(function(g,_r,_i,a,m,_e,d){Object.defineProperty(_e,"__esModule",{value:!0}),_e.default=void 0;var e=_r(d[0]),t=(function(e,t){if("function"==typeof WeakMap)var n=new WeakMap,r=new WeakMap;return(function(e,t){if(!t&&e&&e.__esModule)return e;var o,i,u={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return u;if(o=t?r:n){if(o.has(e))return o.get(e);o.set(e,u)}for(var s in e)"default"!==s&&{}.hasOwnProperty.call(e,s)&&((i=(o=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,s))&&(i.get||i.set)?o(u,s,i):u[s]=e[s]);return u})(e,t)})(_r(d[1])),n=t,r=_r(d[2]);var o=e.StyleSheet.create({container:{flex:1}});_e.default=function(){var i='dark'===(0,e.useColorScheme)();return(0,r.jsxs)(e.View,{style:o.container,children:[(0,r.jsx)(e.StatusBar,{barStyle:i?'light-content':'dark-content'}),(0,r.jsx)(e.View,{style:{height:100}}),(0,r.jsx)(e.Button,{title:'\u8fdb\u5165\u4e92\u8054\u7f51\u533b\u9662',onPress:function(){n.pushByName('hospital',{})}}),(0,r.jsx)(e.View,{style:{height:15}}),(0,r.jsx)(e.Button,{title:'\u8fdb\u5165\u533b\u7f51\u7b7e',onPress:function(){n.pushByName(t.Apps.Ywq,{})}})]})}},10000001,[3,491,243]);
__r(108);
__r(10000000);

查看文件

@ -0,0 +1,4 @@
__d(function(g,r,i,a,m,e,d){var t=r(d[0]),n=r(d[1]),p=t(r(d[2]));n.AppRegistry.registerComponent(r(d[3]).Apps.Hospital,function(){return p.default})},10000000,[5,3,10000001,491]);
__d(function(g,r,i,a,m,e,d){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var t=r(d[0]),n=r(d[1]);var o=t.StyleSheet.create({container:{flex:1}});e.default=function(){var l='dark'===(0,t.useColorScheme)();return(0,n.jsxs)(t.View,{style:o.container,children:[(0,n.jsx)(t.StatusBar,{barStyle:l?'light-content':'dark-content'}),(0,n.jsx)(t.View,{style:{height:100}}),(0,n.jsx)(t.Text,{children:"\u4e92\u8054\u7f51\u533b\u9662"}),(0,n.jsx)(t.Button,{title:'\u8fd4\u56de',onPress:function(){(0,r(d[2]).pop)()}})]})}},10000001,[3,243,491]);
__r(108);
__r(10000000);

查看文件

@ -0,0 +1,4 @@
__d(function(g,r,i,a,m,e,d){var n=r(d[0]),t=r(d[1]),p=n(r(d[2]));t.AppRegistry.registerComponent(r(d[3]).Apps.Ywq,function(){return p.default})},10000000,[5,3,10000001,491]);
__d(function(g,r,i,a,m,e,d){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var t=r(d[0]),n=r(d[1]);var o=t.StyleSheet.create({container:{flex:1}});e.default=function(){var l='dark'===(0,t.useColorScheme)();return(0,n.jsxs)(t.View,{style:o.container,children:[(0,n.jsx)(t.StatusBar,{barStyle:l?'light-content':'dark-content'}),(0,n.jsx)(t.View,{style:{height:100}}),(0,n.jsx)(t.Button,{title:'onConfirm',onPress:function(){}})]})}},10000001,[3,243]);
__r(108);
__r(10000000);

查看文件

@ -0,0 +1,175 @@
package com.facebook.react.runtime
import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.KeyEvent
import com.facebook.react.ReactActivity
import com.facebook.react.ReactDelegate
import com.facebook.react.ReactInstanceEventListener
import com.facebook.react.ReactInstanceManager
import com.facebook.react.ReactRootView
import com.facebook.react.bridge.JSBundleLoader
import com.facebook.react.bridge.ReactContext
import com.facebook.react.common.annotations.DeprecatedInNewArchitecture
import com.facebook.react.defaults.DefaultReactActivityDelegate
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags.enableBridgelessArchitecture
class MultipleReactActivityDelegate(
activity: ReactActivity,
mainComponentName: String,
fabricEnabled: Boolean,
) : DefaultReactActivityDelegate(activity, mainComponentName, fabricEnabled) {
private var mReactDelegate: ReactDelegate? = null
override fun onCreate(savedInstanceState: Bundle?) {
val helper = ReactHostHelper(reactHost as ReactHostImpl)
val mainComponentName = this.mainComponentName
val launchOptions = this.composeLaunchOptions()
val activity = reactActivity
if (Build.VERSION.SDK_INT >= 26 && this.isWideColorGamutEnabled) {
activity.window.colorMode = ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT
}
if (enableBridgelessArchitecture()) {
this.mReactDelegate =
ReactDelegate(
this.plainActivity,
this.reactHost,
mainComponentName,
launchOptions,
)
reactHost?.start()?.waitForCompletion()
val result =
helper.loadBundle(
JSBundleLoader.createAssetLoader(this.reactActivity, "assets://index.android.bundle", false),
)
Log.i("TestApp", "load biz bundle ==> $result")
this.loadApp(mainComponentName)
} else {
this.mReactDelegate =
object : ReactDelegate(
this.plainActivity,
this.reactNativeHost,
mainComponentName,
launchOptions,
this.isFabricEnabled,
) {
override fun createRootView(): ReactRootView {
var rootView: ReactRootView? = this@MultipleReactActivityDelegate.createRootView()
if (rootView == null) {
rootView = super.createRootView()
}
return rootView!!
}
}
reactNativeHost.reactInstanceManager.addReactInstanceEventListener(
object : ReactInstanceEventListener {
override fun onReactContextInitialized(context: ReactContext) {
Log.i("TestApp", "Multiple onReactContextInitialized")
val instance = reactNativeHost.reactInstanceManager.currentReactContext?.catalystInstance
instance?.loadScriptFromAssets(context.assets, "assets://index.android.bundle", false)
Log.i("TestApp", "loaded biz bundle")
if (mainComponentName != null) {
try {
this@MultipleReactActivityDelegate.loadApp(mainComponentName)
} catch (e: Exception) {
Log.e("TestApp", "load app $mainComponentName")
}
}
}
},
)
reactNativeHost.reactInstanceManager.createReactContextInBackground()
}
}
private fun loadAppOldWay() {
}
override fun getReactDelegate(): ReactDelegate = mReactDelegate!!
@DeprecatedInNewArchitecture(message = "Use getReactHost()")
override fun getReactInstanceManager(): ReactInstanceManager = mReactDelegate!!.reactInstanceManager
override fun loadApp(appKey: String?) {
mReactDelegate!!.loadApp(appKey)
plainActivity.setContentView(mReactDelegate!!.reactRootView)
}
override fun onUserLeaveHint() {
if (mReactDelegate != null) {
mReactDelegate!!.onUserLeaveHint()
}
}
override fun onPause() {
mReactDelegate!!.onHostPause()
}
override fun onResume() {
mReactDelegate!!.onHostResume()
// if (mPermissionsCallback != null) {
// mPermissionsCallback!!.invoke()
// mPermissionsCallback = null
// }
}
override fun onDestroy() {
mReactDelegate!!.onHostDestroy()
}
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?,
) {
mReactDelegate!!.onActivityResult(requestCode, resultCode, data, true)
}
override fun onKeyDown(
keyCode: Int,
event: KeyEvent?,
): Boolean = mReactDelegate!!.onKeyDown(keyCode, event)
override fun onKeyUp(
keyCode: Int,
event: KeyEvent?,
): Boolean = mReactDelegate!!.shouldShowDevMenuOrReload(keyCode, event)
override fun onKeyLongPress(
keyCode: Int,
event: KeyEvent?,
): Boolean = mReactDelegate!!.onKeyLongPress(keyCode)
override fun onBackPressed(): Boolean = mReactDelegate!!.onBackPressed()
override fun onNewIntent(intent: Intent?): Boolean = mReactDelegate!!.onNewIntent(intent)
override fun onWindowFocusChanged(hasFocus: Boolean) {
mReactDelegate!!.onWindowFocusChanged(hasFocus)
}
override fun onConfigurationChanged(newConfig: Configuration?) {
mReactDelegate!!.onConfigurationChanged(newConfig)
}
/**
* Get the current [ReactContext] from ReactHost or ReactInstanceManager
*
*
* Do not store a reference to this, if the React instance is reloaded or destroyed, this
* context will no longer be valid.
*/
override fun getCurrentReactContext(): ReactContext = mReactDelegate!!.currentReactContext!!
}

查看文件

@ -0,0 +1,24 @@
package com.facebook.react.runtime
import com.facebook.react.bridge.JSBundleLoader
import com.facebook.react.interfaces.TaskInterface
import com.facebook.react.runtime.internal.bolts.Task
import kotlin.coroutines.Continuation
import kotlin.jvm.internal.Intrinsics
class ReactHostHelper(
private val delegate: ReactHostImpl,
) {
fun loadBundle(bundleLoader: JSBundleLoader): Boolean? {
Intrinsics.checkNotNullParameter(bundleLoader, "bundlerLoader")
val task = delegate.loadBundle(bundleLoader)
task.waitForCompletion()
return task.getResult()
}
fun getOrCreateReactInstance() {
delegate.isInstanceInitialized
}
}

查看文件

@ -6,6 +6,7 @@ import com.trust.ywx.specs.navigation.NavigationHelper
import com.facebook.react.ReactActivityDelegate import com.facebook.react.ReactActivityDelegate
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
import com.facebook.react.defaults.DefaultReactActivityDelegate import com.facebook.react.defaults.DefaultReactActivityDelegate
import com.facebook.react.runtime.MultipleReactActivityDelegate
class BuzActivity : ReactActivity() { class BuzActivity : ReactActivity() {
@ -20,7 +21,11 @@ class BuzActivity : ReactActivity() {
* which allows you to enable New Architecture with a single boolean flags [fabricEnabled] * which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
*/ */
override fun createReactActivityDelegate(): ReactActivityDelegate = override fun createReactActivityDelegate(): ReactActivityDelegate =
DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) if (BuildConfig.BUILD_TYPE == "debug") DefaultReactActivityDelegate(
this,
mainComponentName,
fabricEnabled
) else MultipleReactActivityDelegate(this, mainComponentName, fabricEnabled)
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)

查看文件

@ -13,27 +13,31 @@ import com.trust.ywx.specs.navigation.NavigationPackage
class MainApplication : Application(), ReactApplication { class MainApplication : Application(), ReactApplication {
override val reactNativeHost: ReactNativeHost = override val reactNativeHost: ReactNativeHost =
object : DefaultReactNativeHost(this) { object : DefaultReactNativeHost(this) {
override fun getPackages(): List<ReactPackage> = override fun getPackages(): List<ReactPackage> =
PackageList(this).packages.apply { PackageList(this).packages.apply {
// Packages that cannot be autolinked yet can be added manually here, for example: // Packages that cannot be autolinked yet can be added manually here, for example:
add(NavigationPackage()) add(NavigationPackage())
} }
override fun getJSMainModuleName(): String = "index" override fun getJSMainModuleName(): String =
if (BuildConfig.BUILD_TYPE == "debug") "index" else "commom"
override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG override fun getBundleAssetName(): String =
if (BuildConfig.BUILD_TYPE == "debug") "index.android.bundle" else "common.android.bundle"
override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
}
override val reactHost: ReactHost override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
get() = getDefaultReactHost(applicationContext, reactNativeHost) override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
}
override fun onCreate() { override val reactHost: ReactHost
super.onCreate() get() = getDefaultReactHost(applicationContext, reactNativeHost)
loadReactNative(this)
} override fun onCreate() {
super.onCreate()
loadReactNative(this)
}
} }

查看文件

@ -37,3 +37,4 @@ newArchEnabled=true
# Use this property to enable or disable the Hermes JS engine. # Use this property to enable or disable the Hermes JS engine.
# If set to false, you will be using JSC instead. # If set to false, you will be using JSC instead.
hermesEnabled=true hermesEnabled=true
org.gradle.configuration-cache=true

查看文件

@ -1,4 +0,0 @@
__d(function(g,r,i,a,m,e,d){var n=r(d[0]),t=r(d[1]),p=n(r(d[2]));t.AppRegistry.registerComponent("app",function(){return p.default})},10000000,[5,3,10000001]);
__d(function(g,_r,_i,a,m,_e,d){Object.defineProperty(_e,"__esModule",{value:!0}),_e.default=void 0;var e=_r(d[0]),t=(function(e,t){if("function"==typeof WeakMap)var n=new WeakMap,r=new WeakMap;return(function(e,t){if(!t&&e&&e.__esModule)return e;var o,i,u={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return u;if(o=t?r:n){if(o.has(e))return o.get(e);o.set(e,u)}for(var l in e)"default"!==l&&{}.hasOwnProperty.call(e,l)&&((i=(o=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,l))&&(i.get||i.set)?o(u,l,i):u[l]=e[l]);return u})(e,t)})(_r(d[1])),n=_r(d[2]);var r=e.StyleSheet.create({container:{flex:1}});_e.default=function(){var o='dark'===(0,e.useColorScheme)();return(0,n.jsxs)(e.View,{style:r.container,children:[(0,n.jsx)(e.StatusBar,{barStyle:o?'light-content':'dark-content'}),(0,n.jsx)(e.View,{style:{height:100}}),(0,n.jsx)(e.Button,{title:'\u8fdb\u5165\u4e92\u8054\u7f51\u533b\u9662',onPress:function(){console.log('>>>>',t),t.pushByName('hospital',{})}})]})}},10000001,[3,491,243]);
__r(108);
__r(10000000);

查看文件

@ -3,7 +3,7 @@
"version": "0.0.1", "version": "0.0.1",
"private": true, "private": true,
"scripts": { "scripts": {
"android": "react-native run-android", "android": "react-native run-android --active-arch-only",
"ios": "react-native run-ios", "ios": "react-native run-ios",
"lint": "eslint .", "lint": "eslint .",
"start": "react-native start", "start": "react-native start",

查看文件

@ -28,6 +28,7 @@ function App() {
navigation.pushByName('hospital', {}); navigation.pushByName('hospital', {});
}} }}
/> />
<View style={{ height: 15 }} />
<Button <Button
title={'进入医网签'} title={'进入医网签'}
onPress={() => { onPress={() => {