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

Ability to attach ReactRootView to different Activity #483

Merged
merged 14 commits into from
Feb 5, 2019

Conversation

hypest
Copy link
Contributor

@hypest hypest commented Jan 21, 2019

This is useful for retaining the RN view/context while rotating the device (and letting the Activity get recreated) or even when interested in attaching the view to a completely different Activity (say, preloading RN before the editor Activity appears).

RN is still able to adapt to the new Activity's layout, which is super useful for portrait/landscape/etc.

This PR is not opened for merging yet. Rather, it's purpose is to be able to try it easily and have a discussion.

Implementation Details

The solution here is based on MutableContextWrapper with its ability to change the Context after the ReactRootView has already been created. RN will still receive lifecycle events before and affter the change since those are propagated.

After the Context gets changed, we need to remove the View from its previous parent (if any, happens on rotation) and add it to a new parent.

To test

Use this PR on wpandroid wordpress-mobile/WordPress-Android#9030.

This is useful for retaining the RN view/context. RN is still able to
adapt to the new Activity's layout, which is super useful for portrait/landscape.
Otherwise, multiple Aztec instances autofocus and the exact caret
position is lost on rotation.
@hypest hypest force-pushed the feature/android-attach-to-new-activity branch from f2dd578 to 2550973 Compare February 5, 2019 00:41
}

@Override
public void mediaUploadSync(MediaUploadCallback mediaUploadCallback) {
mPendingMediaUploadCallback = mediaUploadCallback;
onReattachQueryListener.onQueryCurrentProgressForUploadingMedia();
mOnReattachQueryListener.onQueryCurrentProgressForUploadingMedia();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering if there could be a case where this listener can be called before the view is attached to a container. In that case we need to check that are not null(s)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In principal it could indeed be called before attaching the view, but that would be a bug (lifecycle error). Letting that throw would be a better handling, at least for the first implementation.

There is another case though, where the listener won't be null but, it will be old: after rotation and before the View gets re-attached, the listener will point to a previous instance. That can be buggy or crashing. Even in this case though, handling it is not a solution. We can alleviate the crash but, that doesn't recover the situation.

I think the callback-based solution, along with the async nature of title/content getters setters has these shortcomings. We will need a better messaging system.

private void refocus() {
if (mLastFocusedView != null) {
// schedule a request for focus
new Handler(Looper.getMainLooper()).post(new Runnable() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in chat convo this could introduce some lag, but in my opinion it's unlikely to happen on "normal" workflow. Even it that happens, the focus/caret is restored properly with just a bit of delay.

@daniloercoli
Copy link
Contributor

I wasn't fully aware of what were the benefits of MutableContextWrapper till today.
I googled it up a bit and found out the following warning:

Definitely not safe. There are actions on Context that require counter-actions in order to free up resources, e.g. Context.registerComponentCallabacks, Context.registerReceiver, and if you change the Context in the meantime, that means the counter-actions will not be called for the initial context, resulting in resource leaks.

Not quite sure if this can affect us in some way, since we could set the Title and the Content, and then start the RN application. Later we can attach it to a new view, and a different context.

@hypest
Copy link
Contributor Author

hypest commented Feb 5, 2019

I think we will need to keep an eye on this solution anyway. It's hacky from its start. I mean, trying to retain a view while its Activity is rotating is quite against the Android best practices.

It's only a necessity because we want to not touch the Aztec Activity (EditPostActivity over at the wpandroid repo) and continue to allow it to recreate on rotation. We'll want to revise that preference (to not touch Aztec-standalone at all) down the road as Gutenberg-mobile gets more stable.

Copy link
Contributor

@daniloercoli daniloercoli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@hypest hypest merged commit 9dce6ad into develop Feb 5, 2019
@hypest hypest deleted the feature/android-attach-to-new-activity branch February 5, 2019 15:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants