blob: 628e4ccab2ea9ba0e51d4103c26692eab0a4f896 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.weex;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import org.apache.weex.adapter.ClassLoaderAdapter;
import org.apache.weex.adapter.DefaultUriAdapter;
import org.apache.weex.adapter.DefaultWXHttpAdapter;
import org.apache.weex.adapter.IWXConfigAdapter;
import org.apache.weex.adapter.ICrashInfoReporter;
import org.apache.weex.adapter.IDrawableLoader;
import org.apache.weex.adapter.IWXJscProcessManager;
import org.apache.weex.adapter.ITracingAdapter;
import org.apache.weex.adapter.IWXAccessibilityRoleAdapter;
import org.apache.weex.adapter.IWXHttpAdapter;
import org.apache.weex.adapter.IWXImgLoaderAdapter;
import org.apache.weex.adapter.IWXJSExceptionAdapter;
import org.apache.weex.adapter.IWXJsFileLoaderAdapter;
import org.apache.weex.adapter.IWXSoLoaderAdapter;
import org.apache.weex.adapter.IWXUserTrackAdapter;
import org.apache.weex.adapter.URIAdapter;
import org.apache.weex.appfram.navigator.IActivityNavBarSetter;
import org.apache.weex.appfram.navigator.INavigator;
import org.apache.weex.appfram.storage.DefaultWXStorage;
import org.apache.weex.appfram.storage.IWXStorageAdapter;
import org.apache.weex.appfram.websocket.IWebSocketAdapter;
import org.apache.weex.appfram.websocket.IWebSocketAdapterFactory;
import org.apache.weex.bridge.WXBridgeManager;
import org.apache.weex.bridge.WXModuleManager;
import org.apache.weex.bridge.WXValidateProcessor;
import org.apache.weex.common.WXRefreshData;
import org.apache.weex.common.WXRuntimeException;
import org.apache.weex.common.WXThread;
import org.apache.weex.common.WXWorkThreadManager;
import org.apache.weex.font.FontAdapter;
import org.apache.weex.performance.IApmGenerator;
import org.apache.weex.performance.IWXAnalyzer;
import org.apache.weex.ui.WXRenderManager;
import org.apache.weex.utils.WXLogUtils;
import org.apache.weex.utils.WXUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Manger class for weex context.
*/
public class WXSDKManager {
private static volatile WXSDKManager sManager;
private static AtomicInteger sInstanceId = new AtomicInteger(0);
private final WXWorkThreadManager mWXWorkThreadManager;
private WXBridgeManager mBridgeManager;
/** package **/ WXRenderManager mWXRenderManager;
private IWXUserTrackAdapter mIWXUserTrackAdapter;
private IWXImgLoaderAdapter mIWXImgLoaderAdapter;
private IWXSoLoaderAdapter mIWXSoLoaderAdapter;
private IDrawableLoader mDrawableLoader;
private IWXHttpAdapter mIWXHttpAdapter;
private IActivityNavBarSetter mActivityNavBarSetter;
private IWXAccessibilityRoleAdapter mRoleAdapter;
private List<IWXAnalyzer> mWXAnalyzerList;
private IApmGenerator mApmGenerater;
private IWXJsFileLoaderAdapter mWXJsFileLoaderAdapter;
private ICrashInfoReporter mCrashInfo;
private IWXJSExceptionAdapter mIWXJSExceptionAdapter;
private IWXConfigAdapter mConfigAdapter;
private IWXStorageAdapter mIWXStorageAdapter;
private IWXStatisticsListener mStatisticsListener;
private URIAdapter mURIAdapter;
private ClassLoaderAdapter mClassLoaderAdapter;
private IWebSocketAdapterFactory mIWebSocketAdapterFactory;
private ITracingAdapter mTracingAdapter;
private WXValidateProcessor mWXValidateProcessor;
private IWXJscProcessManager mWXJscProcessManager;
// Tell weexv8 to initialize v8, default is true.
private boolean mNeedInitV8 = true;
//add when instance create,rm when instance destroy, not like WXRenderManager
private Map<String,WXSDKInstance> mAllInstanceMap;
private List<InstanceLifeCycleCallbacks> mLifeCycleCallbacks;
private static final int DEFAULT_VIEWPORT_WIDTH = 750;
private WXSDKManager() {
this(new WXRenderManager());
}
private WXSDKManager(WXRenderManager renderManager) {
mWXRenderManager = renderManager;
mBridgeManager = WXBridgeManager.getInstance();
mWXWorkThreadManager = new WXWorkThreadManager();
mWXAnalyzerList = new CopyOnWriteArrayList<>();
mAllInstanceMap = new HashMap<>();
}
/**
* Used in junit test
*/
static void initInstance(WXRenderManager renderManager){
sManager = new WXSDKManager(renderManager);
}
public void registerStatisticsListener(IWXStatisticsListener listener) {
mStatisticsListener = listener;
}
public IWXStatisticsListener getWXStatisticsListener() {
return mStatisticsListener;
}
public void onSDKEngineInitialize() {
if (mStatisticsListener != null) {
mStatisticsListener.onSDKEngineInitialize();
}
}
public void setNeedInitV8(boolean need) {
mNeedInitV8 = need;
}
public boolean needInitV8() {
return mNeedInitV8;
}
public void takeJSHeapSnapshot(String path) {
File file = new File(path);
if (!file.exists()) {
if (!file.mkdir()) {
return;
}
}
String name = String.valueOf(sInstanceId.get());
String filename = path;
if (!path.endsWith(File.separator)) {
filename += File.separator;
}
filename += name;
filename += ".heapsnapshot";
mBridgeManager.takeJSHeapSnapshot(filename);
}
public static WXSDKManager getInstance() {
if (sManager == null) {
synchronized (WXSDKManager.class) {
if(sManager == null) {
sManager = new WXSDKManager();
}
}
}
return sManager;
}
public static int getInstanceViewPortWidth(String instanceId){
WXSDKInstance instance = getInstance().getSDKInstance(instanceId);
if (instance == null) {
return DEFAULT_VIEWPORT_WIDTH;
}
return instance.getInstanceViewPortWidth();
}
static void setInstance(WXSDKManager manager){
sManager = manager;
}
public IActivityNavBarSetter getActivityNavBarSetter() {
return mActivityNavBarSetter;
}
public void setActivityNavBarSetter(IActivityNavBarSetter mActivityNavBarSetter) {
this.mActivityNavBarSetter = mActivityNavBarSetter;
}
public void restartBridge() {
mBridgeManager.restart();
}
public WXBridgeManager getWXBridgeManager() {
return mBridgeManager;
}
public WXRenderManager getWXRenderManager() {
return mWXRenderManager;
}
public IWXJscProcessManager getWXJscProcessManager() {
return mWXJscProcessManager;
}
public WXWorkThreadManager getWXWorkThreadManager() {
return mWXWorkThreadManager;
}
public void setWxConfigAdapter(IWXConfigAdapter mConfigAdapter) {
this.mConfigAdapter = mConfigAdapter;
}
public IWXConfigAdapter getWxConfigAdapter() {
return mConfigAdapter;
}
public @Nullable WXSDKInstance getSDKInstance(String instanceId) {
return instanceId == null? null : mWXRenderManager.getWXSDKInstance(instanceId);
}
public void postOnUiThread(Runnable runnable, long delayMillis) {
mWXRenderManager.postOnUiThread(WXThread.secure(runnable), delayMillis);
}
public Map<String, WXSDKInstance> getAllInstanceMap() {
return mAllInstanceMap;
}
public void destroy() {
if (mWXWorkThreadManager != null) {
mWXWorkThreadManager.destroy();
}
mAllInstanceMap.clear();
}
@Deprecated
public void callback(String instanceId, String funcId, Map<String, Object> data) {
mBridgeManager.callback(instanceId, funcId, data);
}
@Deprecated
public void callback(String instanceId, String funcId, Map<String, Object> data,boolean keepAlive) {
mBridgeManager.callback(instanceId, funcId, data,keepAlive);
}
public void initScriptsFramework(String framework) {
mBridgeManager.initScriptsFramework(framework);
}
public void registerComponents(List<Map<String, Object>> components) {
mBridgeManager.registerComponents(components);
}
public void registerModules(Map<String, Object> modules) {
mBridgeManager.registerModules(modules);
}
/**
* Do not direct invoke this method in Components, use {@link WXSDKInstance#fireEvent(String, String, Map, Map)} instead.
*/
@Deprecated
public void fireEvent(final String instanceId, String ref, String type) {
fireEvent(instanceId, ref, type, new HashMap<String, Object>());
}
/**
* FireEvent back to JS
* Do not direct invoke this method in Components, use {@link WXSDKInstance#fireEvent(String, String, Map, Map)} instead.
*/
@Deprecated
public void fireEvent(final String instanceId, String ref, String type, Map<String, Object> params){
fireEvent(instanceId,ref,type,params,null);
}
/**
* Do not direct invoke this method in Components, use {@link WXSDKInstance#fireEvent(String, String, Map, Map)} instead.
**/
@Deprecated
public void fireEvent(final String instanceId, String ref, String type, Map<String, Object> params,Map<String,Object> domChanges) {
if (WXEnvironment.isApkDebugable() && Looper.getMainLooper().getThread().getId() != Thread.currentThread().getId()) {
throw new WXRuntimeException("[WXSDKManager] fireEvent error");
}
mBridgeManager.fireEventOnNode(instanceId, ref, type, params,domChanges);
}
void createInstance(WXSDKInstance instance, Script code, Map<String, Object> options, String jsonInitData) {
mWXRenderManager.registerInstance(instance);
mBridgeManager.createInstance(instance.getInstanceId(), code, options, jsonInitData);
if (mLifeCycleCallbacks != null) {
for (InstanceLifeCycleCallbacks callbacks : mLifeCycleCallbacks) {
callbacks.onInstanceCreated(instance.getInstanceId());
}
}
}
void refreshInstance(String instanceId, WXRefreshData jsonData) {
mBridgeManager.refreshInstance(instanceId, jsonData);
}
void destroyInstance(String instanceId) {
setCrashInfo(WXEnvironment.WEEX_CURRENT_KEY,"");
if (TextUtils.isEmpty(instanceId)) {
return;
}
if (!WXUtils.isUiThread()) {
throw new WXRuntimeException("[WXSDKManager] destroyInstance error");
}
if (mLifeCycleCallbacks != null) {
for (InstanceLifeCycleCallbacks callbacks : mLifeCycleCallbacks) {
callbacks.onInstanceDestroyed(instanceId);
}
}
mWXRenderManager.removeRenderStatement(instanceId);
mBridgeManager.destroyInstance(instanceId);
WXModuleManager.destroyInstanceModules(instanceId);
}
String generateInstanceId() {
return String.valueOf(sInstanceId.incrementAndGet());
}
public IWXUserTrackAdapter getIWXUserTrackAdapter() {
return mIWXUserTrackAdapter;
}
public IWXImgLoaderAdapter getIWXImgLoaderAdapter() {
return mIWXImgLoaderAdapter;
}
public IWXJsFileLoaderAdapter getIWXJsFileLoaderAdapter() {
return mWXJsFileLoaderAdapter;
}
public IDrawableLoader getDrawableLoader() {
return mDrawableLoader;
}
public IWXJSExceptionAdapter getIWXJSExceptionAdapter() {
return mIWXJSExceptionAdapter;
}
public void setIWXJSExceptionAdapter(IWXJSExceptionAdapter IWXJSExceptionAdapter) {
mIWXJSExceptionAdapter = IWXJSExceptionAdapter;
}
public @NonNull IWXHttpAdapter getIWXHttpAdapter() {
if (mIWXHttpAdapter == null) {
mIWXHttpAdapter = new DefaultWXHttpAdapter();
}
return mIWXHttpAdapter;
}
public IApmGenerator getApmGenerater() {
return mApmGenerater;
}
public @NonNull URIAdapter getURIAdapter() {
if(mURIAdapter == null){
mURIAdapter = new DefaultUriAdapter();
}
return mURIAdapter;
}
public ClassLoaderAdapter getClassLoaderAdapter() {
if(mClassLoaderAdapter == null){
mClassLoaderAdapter = new ClassLoaderAdapter();
}
return mClassLoaderAdapter;
}
public IWXSoLoaderAdapter getIWXSoLoaderAdapter() {
return mIWXSoLoaderAdapter;
}
public List<IWXAnalyzer> getWXAnalyzerList(){
return mWXAnalyzerList;
}
public void addWXAnalyzer(IWXAnalyzer analyzer){
if (!mWXAnalyzerList.contains(analyzer)) {
mWXAnalyzerList.add(analyzer);
}
}
public void rmWXAnalyzer(IWXAnalyzer analyzer){
mWXAnalyzerList.remove(analyzer);
}
void setInitConfig(InitConfig config){
this.mIWXHttpAdapter = config.getHttpAdapter();
this.mIWXImgLoaderAdapter = config.getImgAdapter();
this.mDrawableLoader = config.getDrawableLoader();
this.mIWXStorageAdapter = config.getStorageAdapter();
this.mIWXUserTrackAdapter = config.getUtAdapter();
this.mURIAdapter = config.getURIAdapter();
this.mIWebSocketAdapterFactory = config.getWebSocketAdapterFactory();
this.mIWXJSExceptionAdapter = config.getJSExceptionAdapter();
this.mIWXSoLoaderAdapter = config.getIWXSoLoaderAdapter();
this.mClassLoaderAdapter = config.getClassLoaderAdapter();
this.mApmGenerater = config.getApmGenerater();
this.mWXJsFileLoaderAdapter = config.getJsFileLoaderAdapter();
this.mWXJscProcessManager = config.getJscProcessManager();
}
public IWXStorageAdapter getIWXStorageAdapter(){
if(mIWXStorageAdapter == null){
if(WXEnvironment.sApplication != null){
mIWXStorageAdapter = new DefaultWXStorage(WXEnvironment.sApplication);
}else{
WXLogUtils.e("WXStorageModule", "No Application context found,you should call WXSDKEngine#initialize() method in your application");
}
}
return mIWXStorageAdapter;
}
/**
* Weex embedders can use <code>notifyTrimMemory</code> to reduce
* memory at a proper time.
*
* It's not a good idea to reduce memory at any time, because
* memory trimming is a expense operation, and V8 needs to do
* a full GC and all the inline caches get to be cleared.
*
* The embedder needs to make some scheduling strategies to
* ensure that the embedded application is just on an idle time.
* If the application use the same js bundle to render pages,
* it's not a good idea to trim memory every time of exiting
* pages.
*/
public void notifyTrimMemory() {
mBridgeManager.notifyTrimMemory();
}
/**
* Weex embedders can use <code>notifySerializeCodeCache</code> to
* serialize code caches if the jsfm has the alility to compile 'new Function'
* against js bundles on the weex native side.
*
* It's a good time to serialize a code cache after exiting a weex page.
* Then, the next time of entering the same weex page, V8 would compile
* 'new Function' against the code cache deseriazed from the js bundle.
*/
public void notifySerializeCodeCache() {
mBridgeManager.notifySerializeCodeCache();
}
public @Nullable
IWebSocketAdapter getIWXWebSocketAdapter() {
if (mIWebSocketAdapterFactory != null) {
return mIWebSocketAdapterFactory.createWebSocketAdapter();
}
return null;
}
public void registerValidateProcessor(WXValidateProcessor processor){
this.mWXValidateProcessor = processor;
}
public WXValidateProcessor getValidateProcessor(){
return mWXValidateProcessor;
}
public void setCrashInfoReporter(ICrashInfoReporter mCrashInfo) {
this.mCrashInfo = mCrashInfo;
}
public void setCrashInfo(String key, String value) {
if(mCrashInfo!=null){
mCrashInfo.addCrashInfo(key,value);
}
}
public void setTracingAdapter(ITracingAdapter adapter) {
this.mTracingAdapter = adapter;
}
public ITracingAdapter getTracingAdapter() {
return mTracingAdapter;
}
public void registerInstanceLifeCycleCallbacks(InstanceLifeCycleCallbacks callbacks) {
if (mLifeCycleCallbacks == null) {
mLifeCycleCallbacks = new ArrayList<>();
}
mLifeCycleCallbacks.add(callbacks);
}
public void setAccessibilityRoleAdapter(IWXAccessibilityRoleAdapter adapter) {
this.mRoleAdapter = adapter;
}
public IWXAccessibilityRoleAdapter getAccessibilityRoleAdapter() {
return mRoleAdapter;
}
public interface InstanceLifeCycleCallbacks {
void onInstanceDestroyed(String instanceId);
void onInstanceCreated(String instanceId);
}
private INavigator mNavigator;
public INavigator getNavigator() {
return mNavigator;
}
public void setNavigator(INavigator mNavigator) {
this.mNavigator = mNavigator;
}
private FontAdapter mFontAdapter;
public FontAdapter getFontAdapter(){
if(mFontAdapter == null){
synchronized (this){
if(mFontAdapter == null){
mFontAdapter = new FontAdapter();
}
}
}
return mFontAdapter;
}
}