Skip to content

Commit

Permalink
launch conversion from ASyncTask to Thread
Browse files Browse the repository at this point in the history
Reviewed By: achen1

Differential Revision: D4900998

fbshipit-source-id: af2283525b4e9856d7ff3466096226c4c1209f6b
  • Loading branch information
aaronechiu authored and Maxime Aoustin committed Apr 19, 2017
1 parent 2f93998 commit aa69e76
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 133 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Process;
import android.view.View;

import com.facebook.common.logging.FLog;
Expand Down Expand Up @@ -130,7 +128,6 @@ public interface ReactInstanceEventListener {

private volatile LifecycleState mLifecycleState;
private @Nullable @ThreadConfined(UI) ReactContextInitParams mPendingReactContextInitParams;
private @Nullable @ThreadConfined(UI) ReactContextInitAsyncTask mReactContextInitAsyncTask;
private @Nullable @ThreadConfined(UI) Thread mCreateReactContextThread;

/* accessed from any thread */
Expand All @@ -153,7 +150,7 @@ public interface ReactInstanceEventListener {
private final JSCConfig mJSCConfig;
private final boolean mLazyNativeModulesEnabled;
private final boolean mLazyViewManagersEnabled;
private final boolean mUseStartupThread;
private final boolean mSetupReactContextInBackgroundEnabled;

private final ReactInstanceDevCommandsHandler mDevInterface =
new ReactInstanceDevCommandsHandler() {
Expand Down Expand Up @@ -202,105 +199,6 @@ public JSBundleLoader getJsBundleLoader() {
}
}

/*
* Task class responsible for (re)creating react context in the background. These tasks can only
* be executing one at time, see {@link #recreateReactContextInBackground()}.
*/
private final class ReactContextInitAsyncTask extends
AsyncTask<ReactContextInitParams, Void, Result<ReactApplicationContext>> {
@Override
protected void onPreExecute() {
if (mCurrentReactContext != null) {
tearDownReactContext(mCurrentReactContext);
mCurrentReactContext = null;
}
}

@Override
protected Result<ReactApplicationContext> doInBackground(ReactContextInitParams... params) {
// TODO(t11687218): Look over all threading
// Default priority is Process.THREAD_PRIORITY_BACKGROUND which means we'll be put in a cgroup
// that only has access to a small fraction of CPU time. The priority will be reset after
// this task finishes: https://android.googlesource.com/platform/frameworks/base/+/d630f105e8bc0021541aacb4dc6498a49048ecea/core/java/android/os/AsyncTask.java#256
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);

Assertions.assertCondition(params != null && params.length > 0 && params[0] != null);
try {
JavaScriptExecutor jsExecutor = params[0].getJsExecutorFactory().create();
ReactApplicationContext reactApplicationContext =
createReactContext(jsExecutor, params[0].getJsBundleLoader());
ReactMarker.logMarker(PRE_SETUP_REACT_CONTEXT_START);
return Result.of(reactApplicationContext);
} catch (Exception e) {
// Pass exception to onPostExecute() so it can be handled on the main thread
return Result.of(e);
}
}

@Override
protected void onPostExecute(Result<ReactApplicationContext> result) {
try {
setupReactContext(result.get());
} catch (Exception e) {
mDevSupportManager.handleException(e);
} finally {
mReactContextInitAsyncTask = null;
}

// Handle enqueued request to re-initialize react context.
if (mPendingReactContextInitParams != null) {
recreateReactContextInBackground(
mPendingReactContextInitParams.getJsExecutorFactory(),
mPendingReactContextInitParams.getJsBundleLoader());
mPendingReactContextInitParams = null;
}
}

@Override
protected void onCancelled(Result<ReactApplicationContext> reactApplicationContextResult) {
try {
mMemoryPressureRouter.destroy(reactApplicationContextResult.get());
} catch (Exception e) {
FLog.w(ReactConstants.TAG, "Caught exception after cancelling react context init", e);
} finally {
mReactContextInitAsyncTask = null;
}
}
}

private static class Result<T> {
@Nullable private final T mResult;
@Nullable private final Exception mException;

public static <T, U extends T> Result<T> of(U result) {
return new Result<T>(result);
}

public static <T> Result<T> of(Exception exception) {
return new Result<>(exception);
}

private Result(T result) {
mException = null;
mResult = result;
}

private Result(Exception exception) {
mException = exception;
mResult = null;
}

public T get() throws Exception {
if (mException != null) {
throw mException;
}

Assertions.assertNotNull(mResult);

return mResult;
}
}

/**
* Creates a builder that is capable of creating an instance of {@link ReactInstanceManager}.
*/
Expand All @@ -324,7 +222,7 @@ public static ReactInstanceManagerBuilder builder() {
@Nullable RedBoxHandler redBoxHandler,
boolean lazyNativeModulesEnabled,
boolean lazyViewManagersEnabled,
boolean useStartupThread) {
boolean setupReactContextInBackgroundEnabled) {

initializeSoLoaderIfNecessary(applicationContext);

Expand Down Expand Up @@ -353,7 +251,7 @@ public static ReactInstanceManagerBuilder builder() {
mJSCConfig = jscConfig;
mLazyNativeModulesEnabled = lazyNativeModulesEnabled;
mLazyViewManagersEnabled = lazyViewManagersEnabled;
mUseStartupThread = useStartupThread;
mSetupReactContextInBackgroundEnabled = setupReactContextInBackgroundEnabled;

// Instantiate ReactChoreographer in UI thread.
ReactChoreographer.initialize();
Expand Down Expand Up @@ -632,10 +530,6 @@ public void destroy() {

moveToBeforeCreateLifecycleState();

if (mReactContextInitAsyncTask != null) {
mReactContextInitAsyncTask.cancel(true);
}

if (mCreateReactContextThread != null) {
mCreateReactContextThread.interrupt();
mCreateReactContextThread = null;
Expand Down Expand Up @@ -728,9 +622,7 @@ public void attachMeasuredRootView(ReactRootView rootView) {

// If react context is being created in the background, JS application will be started
// automatically when creation completes, as root view is part of the attached root view list.
if (mReactContextInitAsyncTask == null &&
mCreateReactContextThread == null &&
mCurrentReactContext != null) {
if (mCreateReactContextThread == null && mCurrentReactContext != null) {
attachMeasuredRootViewToInstance(rootView, mCurrentReactContext.getCatalystInstance());
}
}
Expand Down Expand Up @@ -824,29 +716,17 @@ private void onJSBundleLoadedFromServer() {

@ThreadConfined(UI)
private void recreateReactContextInBackground(
JavaScriptExecutor.Factory jsExecutorFactory,
JSBundleLoader jsBundleLoader) {
JavaScriptExecutor.Factory jsExecutorFactory,
JSBundleLoader jsBundleLoader) {
UiThreadUtil.assertOnUiThread();

final ReactContextInitParams initParams = new ReactContextInitParams(
jsExecutorFactory,
jsBundleLoader);
if (mUseStartupThread) {
if (mCreateReactContextThread == null) {
runCreateReactContextOnNewThread(initParams);
} else {
mPendingReactContextInitParams = initParams;
}
if (mCreateReactContextThread == null) {
runCreateReactContextOnNewThread(initParams);
} else {
if (mReactContextInitAsyncTask == null) {
// No background task to create react context is currently running, create and execute one.
mReactContextInitAsyncTask = new ReactContextInitAsyncTask();
mReactContextInitAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, initParams);
} else {
// Background task is currently running, queue up most recent init params to recreate
// context once task completes.
mPendingReactContextInitParams = initParams;
}
mPendingReactContextInitParams = initParams;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class ReactInstanceManagerBuilder {
protected @Nullable RedBoxHandler mRedBoxHandler;
protected boolean mLazyNativeModulesEnabled;
protected boolean mLazyViewManagersEnabled;
protected boolean mUseStartupThread;
protected boolean mSetupReactContextInBackground;

/* package protected */ ReactInstanceManagerBuilder() {
}
Expand Down Expand Up @@ -187,8 +187,9 @@ public ReactInstanceManagerBuilder setLazyViewManagersEnabled(boolean lazyViewMa
return this;
}

public ReactInstanceManagerBuilder setUseStartupThread(boolean useStartupThread) {
mUseStartupThread = useStartupThread;
public ReactInstanceManagerBuilder setSetupReactContextInBackgroundEnabled(
boolean setupReactContextInBackground) {
mSetupReactContextInBackground = setupReactContextInBackground;
return this;
}

Expand Down Expand Up @@ -237,6 +238,6 @@ public ReactInstanceManager build() {
mRedBoxHandler,
mLazyNativeModulesEnabled,
mLazyViewManagersEnabled,
mUseStartupThread);
mSetupReactContextInBackground);
}
}

0 comments on commit aa69e76

Please sign in to comment.