mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-09 09:30:10 +08:00
Release React Native for Android
This is an early release and there are several things that are known not to work if you're porting your iOS app to Android. See the Known Issues guide on the website. We will work with the community to reach platform parity with iOS.
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package com.facebook.react.bridge;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.view.LayoutInflater;
|
||||
|
||||
import com.facebook.react.bridge.queue.CatalystQueueConfiguration;
|
||||
import com.facebook.react.bridge.queue.MessageQueueThread;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
|
||||
/**
|
||||
* Abstract ContextWrapper for Android applicaiton or activity {@link Context} and
|
||||
* {@link CatalystInstance}
|
||||
*/
|
||||
public class ReactContext extends ContextWrapper {
|
||||
|
||||
private final CopyOnWriteArraySet<LifecycleEventListener> mLifecycleEventListeners =
|
||||
new CopyOnWriteArraySet<>();
|
||||
|
||||
private @Nullable CatalystInstance mCatalystInstance;
|
||||
private @Nullable LayoutInflater mInflater;
|
||||
private @Nullable MessageQueueThread mUiMessageQueueThread;
|
||||
private @Nullable MessageQueueThread mNativeModulesMessageQueueThread;
|
||||
private @Nullable MessageQueueThread mJSMessageQueueThread;
|
||||
private @Nullable NativeModuleCallExceptionHandler mNativeModuleCallExceptionHandler;
|
||||
|
||||
public ReactContext(Context base) {
|
||||
super(base);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set and initialize CatalystInstance for this Context. This should be called exactly once.
|
||||
*/
|
||||
public void initializeWithInstance(CatalystInstance catalystInstance) {
|
||||
if (catalystInstance == null) {
|
||||
throw new IllegalArgumentException("CatalystInstance cannot be null.");
|
||||
}
|
||||
if (mCatalystInstance != null) {
|
||||
throw new IllegalStateException("ReactContext has been already initialized");
|
||||
}
|
||||
|
||||
mCatalystInstance = catalystInstance;
|
||||
|
||||
CatalystQueueConfiguration queueConfig = catalystInstance.getCatalystQueueConfiguration();
|
||||
mUiMessageQueueThread = queueConfig.getUIQueueThread();
|
||||
mNativeModulesMessageQueueThread = queueConfig.getNativeModulesQueueThread();
|
||||
mJSMessageQueueThread = queueConfig.getJSQueueThread();
|
||||
}
|
||||
|
||||
public void setNativeModuleCallExceptionHandler(
|
||||
@Nullable NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler) {
|
||||
mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler;
|
||||
}
|
||||
|
||||
// We override the following method so that views inflated with the inflater obtained from this
|
||||
// context return the ReactContext in #getContext(). The default implementation uses the base
|
||||
// context instead, so it couldn't be cast to ReactContext.
|
||||
// TODO: T7538796 Check requirement for Override of getSystemService ReactContext
|
||||
@Override
|
||||
public Object getSystemService(String name) {
|
||||
if (LAYOUT_INFLATER_SERVICE.equals(name)) {
|
||||
if (mInflater == null) {
|
||||
mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
|
||||
}
|
||||
return mInflater;
|
||||
}
|
||||
return getBaseContext().getSystemService(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return handle to the specified JS module for the CatalystInstance associated with this Context
|
||||
*/
|
||||
public <T extends JavaScriptModule> T getJSModule(Class<T> jsInterface) {
|
||||
if (mCatalystInstance == null) {
|
||||
throw new RuntimeException("Trying to invoke JS before CatalystInstance has been set!");
|
||||
}
|
||||
return mCatalystInstance.getJSModule(jsInterface);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the instance of the specified module interface associated with this ReactContext.
|
||||
*/
|
||||
public <T extends NativeModule> T getNativeModule(Class<T> nativeModuleInterface) {
|
||||
if (mCatalystInstance == null) {
|
||||
throw new RuntimeException("Trying to invoke JS before CatalystInstance has been set!");
|
||||
}
|
||||
return mCatalystInstance.getNativeModule(nativeModuleInterface);
|
||||
}
|
||||
|
||||
public CatalystInstance getCatalystInstance() {
|
||||
return Assertions.assertNotNull(mCatalystInstance);
|
||||
}
|
||||
|
||||
public boolean hasActiveCatalystInstance() {
|
||||
return mCatalystInstance != null && !mCatalystInstance.isDestroyed();
|
||||
}
|
||||
|
||||
public void addLifecycleEventListener(LifecycleEventListener listener) {
|
||||
mLifecycleEventListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeLifecycleEventListener(LifecycleEventListener listener) {
|
||||
mLifecycleEventListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called by the hosting Fragment in {@link Fragment#onResume}
|
||||
*/
|
||||
public void onResume() {
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
for (LifecycleEventListener listener : mLifecycleEventListeners) {
|
||||
listener.onHostResume();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called by the hosting Fragment in {@link Fragment#onPause}
|
||||
*/
|
||||
public void onPause() {
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
for (LifecycleEventListener listener : mLifecycleEventListeners) {
|
||||
listener.onHostPause();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called by the hosting Fragment in {@link Fragment#onDestroy}
|
||||
*/
|
||||
public void onDestroy() {
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
for (LifecycleEventListener listener : mLifecycleEventListeners) {
|
||||
listener.onHostDestroy();
|
||||
}
|
||||
if (mCatalystInstance != null) {
|
||||
mCatalystInstance.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
public void assertOnUiQueueThread() {
|
||||
Assertions.assertNotNull(mUiMessageQueueThread).assertIsOnThread();
|
||||
}
|
||||
|
||||
public boolean isOnUiQueueThread() {
|
||||
return Assertions.assertNotNull(mUiMessageQueueThread).isOnThread();
|
||||
}
|
||||
|
||||
public void runOnUiQueueThread(Runnable runnable) {
|
||||
Assertions.assertNotNull(mUiMessageQueueThread).runOnQueue(runnable);
|
||||
}
|
||||
|
||||
public void assertOnNativeModulesQueueThread() {
|
||||
Assertions.assertNotNull(mNativeModulesMessageQueueThread).assertIsOnThread();
|
||||
}
|
||||
|
||||
public boolean isOnNativeModulesQueueThread() {
|
||||
return Assertions.assertNotNull(mNativeModulesMessageQueueThread).isOnThread();
|
||||
}
|
||||
|
||||
public void runOnNativeModulesQueueThread(Runnable runnable) {
|
||||
Assertions.assertNotNull(mNativeModulesMessageQueueThread).runOnQueue(runnable);
|
||||
}
|
||||
|
||||
public void assertOnJSQueueThread() {
|
||||
Assertions.assertNotNull(mJSMessageQueueThread).assertIsOnThread();
|
||||
}
|
||||
|
||||
public boolean isOnJSQueueThread() {
|
||||
return Assertions.assertNotNull(mJSMessageQueueThread).isOnThread();
|
||||
}
|
||||
|
||||
public void runOnJSQueueThread(Runnable runnable) {
|
||||
Assertions.assertNotNull(mJSMessageQueueThread).runOnQueue(runnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes the given exception to the current
|
||||
* {@link com.facebook.react.bridge.NativeModuleCallExceptionHandler} if one exists, rethrowing
|
||||
* otherwise.
|
||||
*/
|
||||
public void handleException(RuntimeException e) {
|
||||
if (mCatalystInstance != null &&
|
||||
!mCatalystInstance.isDestroyed() &&
|
||||
mNativeModuleCallExceptionHandler != null) {
|
||||
mNativeModuleCallExceptionHandler.handleException(e);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user