| /* |
| * 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; |
| } |
| } |