React-native: [Android][0.29] No longer possible to access Activity from SimpleViewManager

Created on 8 Jul 2016  路  18Comments  路  Source: facebook/react-native

According to the 0.29.0 upgrade docs, it's now very easy to extend ReactContextBaseJavaModule and use getCurrentActivity to get the activity reference in native Android modules. However, it no longer appears to be possible to get access to the current activity from native Android UI Components.

Continuing a discussion started here, I need access to the activity so that I can create a FragmentManager to add a Fragment to the FrameLayout being vended from SimpleViewManager. There was a suggestion that ReactContext.getCurrentActivity() be made public, which seems like a bad idea, but I can't think of another way.

Locked

Most helpful comment

Having getPackages take an Activity parameter is a much worse idea than making ReactContext#getCurrentActivity() public, for the following reasons:

  1. We don't want to tie package / module / viewmanager (and ultimately ReactContext / react instance) creation to an Activity, as we want to be able to initialize a react instance in any context.
  2. As the _current_ in getCurrentActivity() suggests, the Activity can change over time. Holding a reference to whatever the activity was at react instance creation time is both incorrect and a memory leak.

As long as we properly document getCurrentActivity() (I think it already is documented in caps that you shouldn't hold references to the result), it should be fine to make it public.

All 18 comments

Yeah, that's me discussing the issue in those comments also 馃槢 . After that discussion went nowhere, I decided to open this issue.

@marcshilling yes, but you didn't reply if view.getContext works.

It didn't.

hi . this is my workaround to solve this problem . hope it will help u
https://github.com/InnerPeace080/react-native/commit/c0838f0ce3f7348dfcce96b56b685bcc4a633edf

now. we can use getPackages(Activity activity)

@InnerPeace080 you should send a pull request so we can get this in core!

+1 I also cannot access Activity any longer, I need it in the constructor phase in order to get a SplashScreen working. Calling getCurrentActivity() in the constructor simply returns null.

public class SplashScreen extends ReactContextBaseJavaModule {

    public SplashScreen(ReactApplicationContext reactContext) {
        super(reactContext);

        getCurrentActivity() // null
    }

@nickjanssen that's actually different from the issue being discussed here. You are extending ReactContextBaseJavaModule, which has access to getCurrentActivity(). See this comment about why you can't use getCurrentActivity() in the constructor.

This issue is regarding SimpleViewManager extensions not having getCurrentActivity(), which is an issue that still remains in 0.30.0.

@foghina any thoughts on this? Seems like something super useful to get fixed.

Having getPackages take an Activity parameter is a much worse idea than making ReactContext#getCurrentActivity() public, for the following reasons:

  1. We don't want to tie package / module / viewmanager (and ultimately ReactContext / react instance) creation to an Activity, as we want to be able to initialize a react instance in any context.
  2. As the _current_ in getCurrentActivity() suggests, the Activity can change over time. Holding a reference to whatever the activity was at react instance creation time is both incorrect and a memory leak.

As long as we properly document getCurrentActivity() (I think it already is documented in caps that you shouldn't hold references to the result), it should be fine to make it public.

This is fixed in v0.31.0 because you can now call getCurrentActivity() on ReactApplicationContext 馃憤

In SimpleViewManager#createViewInstance(), ThemedReactContext#getCurrentActivity() seems to return null.
This is probably because of the Activity is not initialized when ReactNativeHost is created in the Application.

@lschmierer correct

So, what to do in this case? Is there any way to create the ViewManager later on?

I'm not sure. What I'm doing is creating a placeholder object:

    @Override
    protected FrameLayout createViewInstance(ThemedReactContext context) {
        mFrameLayout = new FrameLayout(context);
        return mFrameLayout;
    }

And then actually doing the work of adding the activity-dependent view to the FrameLayout later on when props change.

Thank you, this seems to be a decent woraround!

In SimpleViewManager#createViewInstance(), ThemedReactContext#getCurrentActivity() seems to return null.

Hmm, that's a bug IMO. It happens because we call startApplication in onCreate() but we only set the current activity in onResume(). Created #9310 to track.

ThemedReactContext#getCurrentActivity() seems to be allways null in react-native version 0.31.0. At least on property setting it is still null.
@marcshilling on which react-native version did your workaround worked?

Was this page helpful?
0 / 5 - 0 ratings