Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Busy-wait for activity on getLaunchArgs() #7822

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.reactnativenavigation.react;

import static com.reactnativenavigation.utils.UiUtils.pxToDp;

import android.app.Activity;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

Expand Down Expand Up @@ -32,10 +36,6 @@
import java.util.ArrayList;
import java.util.Objects;

import static com.reactnativenavigation.utils.UiUtils.pxToDp;

import android.app.Activity;

public class NavigationModule extends ReactContextBaseJavaModule {
private static final String NAME = "RNNBridgeModule";

Expand All @@ -44,6 +44,7 @@ public class NavigationModule extends ReactContextBaseJavaModule {
private final JSONParser jsonParser;
private final LayoutFactory layoutFactory;
private EventEmitter eventEmitter;
private final NullRNActivityWorkaround nullRNActivityWorkaround;

@SuppressWarnings("WeakerAccess")
public NavigationModule(ReactApplicationContext reactContext, ReactInstanceManager reactInstanceManager, LayoutFactory layoutFactory) {
Expand All @@ -55,6 +56,8 @@ public NavigationModule(ReactApplicationContext reactContext, ReactInstanceManag
this.reactInstanceManager = reactInstanceManager;
this.jsonParser = jsonParser;
this.layoutFactory = layoutFactory;
this.nullRNActivityWorkaround = new NullRNActivityWorkaround(reactContext);

reactContext.addLifecycleEventListener(new LifecycleEventListenerAdapter() {
@Override
public void onHostPause() {
Expand Down Expand Up @@ -87,7 +90,8 @@ public String getName() {

@ReactMethod
public void getLaunchArgs(String commandId, Promise promise) {
promise.resolve(LaunchArgsParser.parse(activity()));
Activity activity = nullRNActivityWorkaround.getActivity();
promise.resolve(LaunchArgsParser.parse(activity));
}

private WritableMap createNavigationConstantsMap() {
Expand Down Expand Up @@ -211,6 +215,15 @@ public void dismissAllOverlays(String commandId, Promise promise) {
handle(() -> navigator().dismissAllOverlays(new NativeCommandListener("dismissAllOverlays", commandId, promise, eventEmitter, now)));
}

@Override
public void onCatalystInstanceDestroy() {
final NavigationActivity navigationActivity = activity();
if (navigationActivity != null) {
navigationActivity.onCatalystInstanceDestroy();
}
super.onCatalystInstanceDestroy();
}

private Navigator navigator() {
return activity().getNavigator();
}
Expand All @@ -232,13 +245,4 @@ protected void handle(Runnable task) {
protected NavigationActivity activity() {
return (NavigationActivity) getCurrentActivity();
}

@Override
public void onCatalystInstanceDestroy() {
final NavigationActivity navigationActivity = activity();
if (navigationActivity != null) {
navigationActivity.onCatalystInstanceDestroy();
}
super.onCatalystInstanceDestroy();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.reactnativenavigation.react

import android.app.Activity
import android.util.Log
import com.facebook.react.bridge.LifecycleEventListener
import com.facebook.react.bridge.ReactApplicationContext
import com.reactnativenavigation.utils.busyRetry
import java.lang.ref.WeakReference

private const val ACTIVITY_WAIT_INTERVAL = 100L
private const val ACTIVITY_WAIT_TRIES = 150

private const val LOG_TAG = "RNN.NullActivity"

/**
* This is a helper class to work-around this RN problem: https://github.com/facebook/react-native/issues/37518
*
* It is, hopefully, temporary.
*/
class NullRNActivityWorkaround(reactAppContext: ReactApplicationContext) {
private val reactAppContext: WeakReference<ReactApplicationContext>
@Volatile
private var hasHost = true

init {
this.reactAppContext = WeakReference(reactAppContext)
reactAppContext.addLifecycleEventListener(object: LifecycleEventListener {
override fun onHostDestroy() {
Log.d(LOG_TAG, "HOST_DESTROY")
hasHost = false
}
override fun onHostResume() {
Log.d(LOG_TAG, "HOST_RESUME")
hasHost = true
}
override fun onHostPause() {}
})
}

fun getActivity(): Activity? {
waitForActivity()
return reactAppContext.get()?.currentActivity
}

private fun waitForActivity() {
val isActivityReady = { (reactAppContext.get()?.hasCurrentActivity() ?: false) }

busyRetry(ACTIVITY_WAIT_TRIES, ACTIVITY_WAIT_INTERVAL) { tries ->
if (!isActivityReady() && hasHost) {
Log.d(LOG_TAG, "Busy-waiting for activity! Try: #$tries...")
true
} else false
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.reactnativenavigation.utils

fun busyRetry(times: Int, interval: Long, callback: (tries: Int) -> Boolean) {
var tries = 0
while (tries < times && !callback(tries)) {
sleepSafe(interval)
tries++
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.reactnativenavigation.utils

fun sleepSafe(ms: Long) {
try {
Thread.sleep(ms)
} catch (e: InterruptedException) {
e.printStackTrace()
}
}
Loading