11package com.callstack.reactnativebrownfield
22
33import android.app.Application
4- import android.content.Context
54import android.os.Bundle
65import android.widget.FrameLayout
76import androidx.activity.OnBackPressedCallback
87import androidx.fragment.app.FragmentActivity
98import androidx.lifecycle.DefaultLifecycleObserver
109import androidx.lifecycle.LifecycleOwner
1110import com.callstack.reactnativebrownfield.utils.VersionUtils
12- import com.facebook.react.ReactApplication
1311import com.facebook.react.ReactHost
12+ import com.facebook.react.ReactInstanceEventListener
1413import com.facebook.react.ReactPackage
14+ import com.facebook.react.bridge.ReactContext
15+ import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
16+ import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
1517import com.facebook.react.soloader.OpenSourceMergedSoMapping
1618import com.facebook.soloader.SoLoader
1719import java.util.concurrent.atomic.AtomicBoolean
18- import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
19- import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
2020
2121fun interface OnJSBundleLoaded {
22- operator fun invoke (initialized : Boolean )
22+ operator fun invoke (initialized : Boolean )
2323}
2424
2525/* *
@@ -30,136 +30,135 @@ fun interface OnJSBundleLoaded {
3030private const val RN_THRESHOLD_VERSION = " 0.80.0"
3131
3232class ReactNativeBrownfield private constructor(val reactHost : ReactHost ) {
33- companion object {
34- private lateinit var instance: ReactNativeBrownfield
35- private val initialized = AtomicBoolean ()
33+ companion object {
34+ private lateinit var instance: ReactNativeBrownfield
35+ private val initialized = AtomicBoolean ()
3636
37- @JvmStatic
38- val shared: ReactNativeBrownfield get() = instance
37+ @JvmStatic
38+ val shared: ReactNativeBrownfield get() = instance
3939
40- private fun loadNativeLibs (application : Application ) {
41- val rnVersion = BuildConfig .RN_VERSION
40+ private fun loadNativeLibs (application : Application ) {
41+ val rnVersion = BuildConfig .RN_VERSION
4242
43- if (VersionUtils .isVersionLessThan(rnVersion, RN_THRESHOLD_VERSION )) {
44- SoLoader .init (application.applicationContext, OpenSourceMergedSoMapping )
45- load()
46- }
47- }
43+ if (VersionUtils .isVersionLessThan(rnVersion, RN_THRESHOLD_VERSION )) {
44+ SoLoader .init (application.applicationContext, OpenSourceMergedSoMapping )
45+ load()
46+ }
47+ }
4848
49- @JvmStatic
50- @JvmOverloads
51- fun initialize (
52- application : Application ,
53- reactHost : ReactHost ,
54- onJSBundleLoaded : OnJSBundleLoaded ? = null
55- ) {
56- if (! initialized.getAndSet(true )) {
57- loadNativeLibs(application)
58- instance = ReactNativeBrownfield (reactHost)
59-
60- preloadReactNative {
61- onJSBundleLoaded?.invoke(true )
49+ @JvmStatic
50+ @JvmOverloads
51+ fun initialize (
52+ application : Application ,
53+ reactHost : ReactHost ,
54+ onJSBundleLoaded : OnJSBundleLoaded ? = null
55+ ) {
56+ if (! initialized.getAndSet(true )) {
57+ loadNativeLibs(application)
58+ instance = ReactNativeBrownfield (reactHost)
59+
60+ preloadReactNative {
61+ onJSBundleLoaded?.invoke(true )
62+ }
63+ }
6264 }
63- }
64- }
6565
66- @JvmStatic
67- @JvmOverloads
68- fun initialize (
69- application : Application ,
70- options : HashMap <String , Any >,
71- onJSBundleLoaded : OnJSBundleLoaded ? = null
72- ) {
73- val reactHost: ReactHost by lazy {
74- getDefaultReactHost(
75- context = application,
76- packageList = (options[" packages" ] as ? List <* > ? : emptyList<ReactPackage >())
77- .filterIsInstance<ReactPackage >(),
78- )
79- }
80-
81- initialize(application, reactHost, onJSBundleLoaded)
82- }
66+ @JvmStatic
67+ @JvmOverloads
68+ fun initialize (
69+ application : Application ,
70+ options : HashMap <String , Any >,
71+ onJSBundleLoaded : OnJSBundleLoaded ? = null
72+ ) {
73+ val reactHost: ReactHost by lazy {
74+ getDefaultReactHost(
75+ context = application,
76+ packageList = (options[" packages" ] as ? List <* > ? : emptyList<ReactPackage >())
77+ .filterIsInstance<ReactPackage >(),
78+ jsRuntimeFactory = null
79+ )
80+ }
81+
82+ initialize(application, reactHost, onJSBundleLoaded)
83+ }
8384
84- @JvmStatic
85- @JvmOverloads
86- fun initialize (
87- application : Application ,
88- packages : List <ReactPackage >,
89- onJSBundleLoaded : OnJSBundleLoaded ? = null
90- ) {
91- val options = hashMapOf(" packages" to packages, " mainModuleName" to " index" )
85+ @JvmStatic
86+ @JvmOverloads
87+ fun initialize (
88+ application : Application ,
89+ packages : List <ReactPackage >,
90+ onJSBundleLoaded : OnJSBundleLoaded ? = null
91+ ) {
92+ val options = hashMapOf(" packages" to packages, " mainModuleName" to " index" )
9293
93- initialize(application, options, onJSBundleLoaded)
94- }
94+ initialize(application, options, onJSBundleLoaded)
95+ }
9596
96- private fun preloadReactNative (callback : ((Boolean ) -> Unit )) {
97- // val reactInstanceManager = shared.reactHost.
98- // reactInstanceManager.addReactInstanceEventListener(object :
99- // ReactInstanceEventListener {
100- // override fun onReactContextInitialized(reactContext: ReactContext) {
101- // callback(true)
102- // reactInstanceManager.removeReactInstanceEventListener(this)
103- // }
104- // })
105- // reactInstanceManager?.createReactContextInBackground()
106- // }
97+ private fun preloadReactNative (callback : ((Boolean ) -> Unit )) {
98+ shared.reactHost.addReactInstanceEventListener(object :
99+ ReactInstanceEventListener {
100+ override fun onReactContextInitialized (context : ReactContext ) {
101+ callback(true )
102+ shared.reactHost.removeReactInstanceEventListener(this )
103+ }
104+ })
105+ shared.reactHost.start()
106+ }
107107 }
108- }
109108
110109 fun createView (
111- activity : FragmentActivity ? ,
112- moduleName : String ,
113- reactDelegate : ReactDelegateWrapper ? = null,
114- launchOptions : Bundle ? = null,
110+ activity : FragmentActivity ? ,
111+ moduleName : String ,
112+ reactDelegate : ReactDelegateWrapper ? = null,
113+ launchOptions : Bundle ? = null,
115114 ): FrameLayout {
116- val reactHost = shared.reactHost
117- val resolvedDelegate =
118- reactDelegate ? : ReactDelegateWrapper (activity, reactHost, moduleName, launchOptions)
119-
120- val mBackPressedCallback: OnBackPressedCallback = object : OnBackPressedCallback (true ) {
121- override fun handleOnBackPressed () {
122- // invoked for JS stack back navigation
123- resolvedDelegate.onBackPressed()
115+ val reactHost = shared.reactHost
116+ val resolvedDelegate =
117+ reactDelegate ? : ReactDelegateWrapper (activity, reactHost, moduleName, launchOptions)
118+
119+ val mBackPressedCallback: OnBackPressedCallback = object : OnBackPressedCallback (true ) {
120+ override fun handleOnBackPressed () {
121+ // invoked for JS stack back navigation
122+ resolvedDelegate.onBackPressed()
123+ }
124124 }
125- }
126-
127- // Register back press callback
128- activity?.onBackPressedDispatcher?.addCallback(mBackPressedCallback)
129- // invoked on the last RN screen exit
130- resolvedDelegate.setHardwareBackHandler {
131- mBackPressedCallback.isEnabled = false
132- activity?.onBackPressedDispatcher?.onBackPressed()
133- }
134-
135- /* *
136- * When createView method is called in ReactNativeFragment, a reactDelegate
137- * instance is required. In such a case, we use the lifeCycle events of the fragment.
138- * When createView method is called elsewhere, then reactDelegate is not required.
139- * In such a case, we set the lifeCycle observer.
140- */
141- if (reactDelegate == null ) {
142- activity?.lifecycle?.addObserver(getLifeCycleObserver(resolvedDelegate))
143- }
144-
145- resolvedDelegate.loadApp()
146- return resolvedDelegate.reactRootView!!
147- }
148125
149- private fun getLifeCycleObserver (reactDelegate : ReactDelegateWrapper ): DefaultLifecycleObserver {
150- return object : DefaultLifecycleObserver {
151- override fun onResume (owner : LifecycleOwner ) {
152- reactDelegate.onReactHostResume()
126+ // Register back press callback
127+ activity?.onBackPressedDispatcher?.addCallback(mBackPressedCallback)
128+ // invoked on the last RN screen exit
129+ resolvedDelegate.setHardwareBackHandler {
130+ mBackPressedCallback.isEnabled = false
131+ activity?.onBackPressedDispatcher?.onBackPressed()
153132 }
154133
155- override fun onPause (owner : LifecycleOwner ) {
156- reactDelegate.onHostPause()
134+ /* *
135+ * When createView method is called in ReactNativeFragment, a reactDelegate
136+ * instance is required. In such a case, we use the lifeCycle events of the fragment.
137+ * When createView method is called elsewhere, then reactDelegate is not required.
138+ * In such a case, we set the lifeCycle observer.
139+ */
140+ if (reactDelegate == null ) {
141+ activity?.lifecycle?.addObserver(getLifeCycleObserver(resolvedDelegate))
157142 }
158143
159- override fun onDestroy (owner : LifecycleOwner ) {
160- reactDelegate.onHostDestroy()
161- owner.lifecycle.removeObserver(this ) // Cleanup to avoid leaks
144+ resolvedDelegate.loadApp()
145+ return resolvedDelegate.reactRootView!!
146+ }
147+
148+ private fun getLifeCycleObserver (reactDelegate : ReactDelegateWrapper ): DefaultLifecycleObserver {
149+ return object : DefaultLifecycleObserver {
150+ override fun onResume (owner : LifecycleOwner ) {
151+ reactDelegate.onReactHostResume()
152+ }
153+
154+ override fun onPause (owner : LifecycleOwner ) {
155+ reactDelegate.onHostPause()
156+ }
157+
158+ override fun onDestroy (owner : LifecycleOwner ) {
159+ reactDelegate.onHostDestroy()
160+ owner.lifecycle.removeObserver(this ) // Cleanup to avoid leaks
161+ }
162162 }
163- }
164163 }
165164}
0 commit comments