Commit 83982112 authored by Yacumima's avatar Yacumima

use embedding engine

parent f4427cf1
...@@ -24,71 +24,72 @@ ...@@ -24,71 +24,72 @@
package com.taobao.idlefish.flutterboost; package com.taobao.idlefish.flutterboost;
import android.app.Activity; import android.app.Activity;
import android.content.Context;
import android.os.Looper;
import android.support.annotation.NonNull;
import com.taobao.idlefish.flutterboost.interfaces.IFlutterViewContainer; import com.taobao.idlefish.flutterboost.interfaces.IFlutterEngineProvider;
import com.taobao.idlefish.flutterboost.interfaces.IFlutterViewProvider;
import com.taobao.idlefish.flutterboost.interfaces.IPlatform;
public class FlutterViewProvider implements IFlutterViewProvider { import io.flutter.app.FlutterPluginRegistry;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterShellArgs;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.platform.PlatformViewRegistry;
import io.flutter.view.FlutterMain;
import io.flutter.view.FlutterNativeView;
import io.flutter.view.FlutterView;
import io.flutter.view.TextureRegistry;
private final IPlatform mPlatform; public class BoostEngineProvider implements IFlutterEngineProvider {
private BoostFlutterNativeView mFlutterNativeView = null; static final BoostEngineProvider sInstance = new BoostEngineProvider();
private BoostFlutterView mFlutterView = null;
FlutterViewProvider(IPlatform platform){
mPlatform = platform;
}
private BoostEngine mEngine = null;
private BoostEngineProvider() {
}
@Override @Override
public BoostFlutterView createFlutterView(IFlutterViewContainer container) { public FlutterEngine createEngine(Context context) {
Activity activity = mPlatform.getMainActivity();
if(activity == null) { Utils.assertCallOnMainThread();
Debuger.log("create Flutter View not with MainActivity");
activity = container.getActivity();
}
if (mFlutterView == null) { if (mEngine == null) {
mFlutterView = new BoostFlutterView(activity, null, createFlutterNativeView(container)); FlutterShellArgs flutterShellArgs = new FlutterShellArgs(new String[0]);
} FlutterMain.ensureInitializationComplete(
return mFlutterView; context.getApplicationContext(), flutterShellArgs.toArray());
}
@Override mEngine = new BoostEngine(context.getApplicationContext());
public BoostFlutterNativeView createFlutterNativeView(IFlutterViewContainer container) { mEngine.startRun();
if (mFlutterNativeView == null) {
mFlutterNativeView = new BoostFlutterNativeView(container.getActivity().getApplicationContext());
} }
return mFlutterNativeView; return mEngine;
} }
@Override @Override
public BoostFlutterView tryGetFlutterView() { public FlutterEngine tryGetEngine() {
return mFlutterView; return mEngine;
} }
@Override public static class BoostEngine extends FlutterEngine {
public void stopFlutterView() { final Context mContext;
final BoostFlutterView view = mFlutterView;
if(view != null) { public BoostEngine(@NonNull Context context) {
view.boostStop(); super(context);
} mContext = context;
} }
public void startRun() {
if (!getDartExecutor().isExecutingDart()) {
getNavigationChannel().setInitialRoute("/");
@Override DartExecutor.DartEntrypoint entryPoint = new DartExecutor.DartEntrypoint(
public void reset() { mContext.getResources().getAssets(),
if(mFlutterNativeView != null) { FlutterMain.findAppBundlePath(mContext),
mFlutterNativeView.boostDestroy(); "main");
mFlutterNativeView = null; getDartExecutor().executeDartEntrypoint(entryPoint);
} }
if(mFlutterView != null) {
mFlutterView.boostDestroy();
mFlutterView = null;
} }
} }
} }
...@@ -23,190 +23,242 @@ ...@@ -23,190 +23,242 @@
*/ */
package com.taobao.idlefish.flutterboost; package com.taobao.idlefish.flutterboost;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.content.Intent;
import android.os.Build; import android.os.Bundle;
import android.support.v4.view.ViewCompat; import android.util.Log;
import android.text.TextUtils; import android.view.ViewGroup;
import android.util.AttributeSet; import android.widget.FrameLayout;
import android.view.SurfaceHolder;
import android.view.WindowInsets;
import com.taobao.idlefish.flutterboost.NavigationService.NavigationService; import java.util.LinkedList;
import java.util.List;
import java.lang.reflect.Field; import io.flutter.embedding.android.FlutterView;
import java.util.HashMap; import io.flutter.embedding.engine.FlutterEngine;
import java.util.Map; import io.flutter.embedding.engine.renderer.OnFirstFrameRenderedListener;
import io.flutter.plugin.platform.PlatformPlugin;
import io.flutter.view.FlutterNativeView; public class BoostFlutterView extends FrameLayout {
import io.flutter.view.FlutterView;
public class BoostFlutterView extends FlutterView { private FlutterEngine mFlutterEngine;
private boolean mFirstFrameCalled = false; private FlutterView mFlutterView;
private boolean mResumed = false;
private WindowInsets mCurrentWindowInsets;
private BoostCallback mBoostCallback; private PlatformPlugin mPlatformPlugin;
public BoostFlutterView(Context context, AttributeSet attrs, FlutterNativeView nativeView) { private Bundle mArguments;
super(context, attrs, nativeView);
super.addFirstFrameListener(new FirstFrameListener() { private BoostPluginRegistry mBoostPluginRegistry;
private final List<OnFirstFrameRenderedListener> mFirstFrameRenderedListeners = new LinkedList<>();
private final OnFirstFrameRenderedListener mOnFirstFrameRenderedListener = new OnFirstFrameRenderedListener() {
@Override @Override
public void onFirstFrame() { public void onFirstFrameRendered() {
mFirstFrameCalled = true; final Object[] listeners = mFirstFrameRenderedListeners.toArray();
for (Object obj : listeners) {
((OnFirstFrameRenderedListener) obj).onFirstFrameRendered();
}
} }
}); };
try { public BoostFlutterView(Context context, FlutterEngine engine, Bundle args) {
Field field = FlutterView.class.getDeclaredField("mSurfaceCallback"); super(context);
field.setAccessible(true); mFlutterEngine = engine;
SurfaceHolder.Callback cb = (SurfaceHolder.Callback)field.get(this); mArguments = args;
getHolder().removeCallback(cb); init();
mBoostCallback = new BoostCallback(cb);
getHolder().addCallback(mBoostCallback);
}catch (Throwable t){
Debuger.exception(t);
} }
private void init() {
if (mFlutterEngine == null) {
mFlutterEngine = createFlutterEngine(getContext());
} }
@Override if (mArguments == null) {
public void onStart() { mArguments = new Bundle();
//do nothing...
} }
@Override mPlatformPlugin = new PlatformPlugin((Activity) getContext(), mFlutterEngine.getPlatformChannel());
public void onPostResume() {
//do nothing... mFlutterView = new FlutterView(getContext(), getRenderMode(), getTransparencyMode());
requestFocus(); addView(mFlutterView, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
mFlutterView.addOnFirstFrameRenderedListener(mOnFirstFrameRenderedListener);
mBoostPluginRegistry = new BoostPluginRegistry(mFlutterEngine,(Activity)getContext());
FlutterBoostPlugin.platform().onRegisterPlugins(mBoostPluginRegistry);
} }
@Override protected FlutterEngine createFlutterEngine(Context context) {
public void onPause() { return BoostEngineProvider.sInstance.createEngine(context);
//do nothing...
} }
@Override public void addFirstFrameRendered(OnFirstFrameRenderedListener listener) {
public void onStop() { mFirstFrameRenderedListeners.add(listener);
//do nothing...
} }
@Override public void removeFirstFrameRendered(OnFirstFrameRenderedListener listener) {
public FlutterNativeView detach() { mFirstFrameRenderedListeners.remove(listener);
//do nothing...
return getFlutterNativeView();
} }
@Override
public void destroy() { protected FlutterView.RenderMode getRenderMode() {
//do nothing... String renderModeName = mArguments.getString("flutterview_render_mode", FlutterView.RenderMode.surface.name());
return FlutterView.RenderMode.valueOf(renderModeName);
}
protected FlutterView.TransparencyMode getTransparencyMode() {
String transparencyModeName = mArguments.getString("flutterview_transparency_mode", FlutterView.TransparencyMode.transparent.name());
return FlutterView.TransparencyMode.valueOf(transparencyModeName);
} }
@Override @Override
public Bitmap getBitmap() { protected void onAttachedToWindow() {
if(getFlutterNativeView() == null || !getFlutterNativeView().isAttached()) { super.onAttachedToWindow();
Debuger.exception("FlutterView not attached!"); mPlatformPlugin.onPostResume();
return null;
} }
return super.getBitmap(); public void onResume() {
Debuger.log("BoostFlutterView onResume");
mFlutterEngine.getLifecycleChannel().appIsResumed();
} }
public boolean firstFrameCalled() { // public void onPostResume() {
return mFirstFrameCalled; // Debuger.log("BoostFlutterView onPostResume");
// mPlatformPlugin.onPostResume();
// }
public void onPause() {
Debuger.log("BoostFlutterView onPause");
mFlutterEngine.getLifecycleChannel().appIsInactive();
} }
public void onStop() {
Debuger.log("BoostFlutterView onStop");
mFlutterEngine.getLifecycleChannel().appIsPaused();
}
public void boostResume() { public void onAttach() {
if (!mResumed) { Debuger.log("BoostFlutterView onAttach");
mResumed = true; mFlutterView.attachToFlutterEngine(mFlutterEngine);
super.onPostResume();
Debuger.log("resume flutter view");
} }
public void onDetach() {
Debuger.log("BoostFlutterView onDetach");
mFlutterView.removeOnFirstFrameRenderedListener(mOnFirstFrameRenderedListener);
mFlutterView.detachFromFlutterEngine();
} }
public void boostStop() { public void onDestroy() {
if (mResumed) { Debuger.log("BoostFlutterView onDestroy");
super.onStop(); mPlatformPlugin = null;
Debuger.log("stop flutter view"); mFlutterEngine = null;
mResumed = false;
} }
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
onDetach();
} }
public boolean isResumed() { public void onBackPressed() {
return mResumed; Log.d("FlutterFragment", "onBackPressed()");
if (mFlutterEngine != null) {
mFlutterEngine.getNavigationChannel().popRoute();
} else {
Log.w("FlutterFragment", "Invoked onBackPressed() before FlutterFragment was attached to an Activity.");
} }
public void boostDestroy() {
super.destroy();
} }
public void scheduleFrame(){ public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (mResumed) { if (mFlutterEngine != null) {
Map<String,String> map = new HashMap<>(); mFlutterEngine.getPluginRegistry().onRequestPermissionsResult(requestCode, permissions, grantResults);
map.put("type","scheduleFrame"); } else {
NavigationService.getService().emitEvent(map); Log.w("FlutterFragment", "onRequestPermissionResult() invoked before FlutterFragment was attached to an Activity.");
} }
} }
class BoostCallback implements SurfaceHolder.Callback { public void onNewIntent(Intent intent) {
if (mFlutterEngine != null) {
mFlutterEngine.getPluginRegistry().onNewIntent(intent);
} else {
Log.w("FlutterFragment", "onNewIntent() invoked before FlutterFragment was attached to an Activity.");
}
final SurfaceHolder.Callback mCallback; }
BoostCallback(SurfaceHolder.Callback cb){ public void onActivityResult(int requestCode, int resultCode, Intent data) {
this.mCallback = cb; if (mFlutterEngine != null) {
mFlutterEngine.getPluginRegistry().onActivityResult(requestCode, resultCode, data);
} else {
Log.w("FlutterFragment", "onActivityResult() invoked before FlutterFragment was attached to an Activity.");
} }
@Override
public void surfaceCreated(SurfaceHolder holder) {
//Debuger.log("flutterView surfaceCreated");
try {
mCallback.surfaceCreated(holder);
}catch (Throwable t){
Debuger.exception(t);
} }
public void onUserLeaveHint() {
if (mFlutterEngine != null) {
mFlutterEngine.getPluginRegistry().onUserLeaveHint();
} else {
Log.w("FlutterFragment", "onUserLeaveHint() invoked before FlutterFragment was attached to an Activity.");
} }
@Override }
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//Debuger.log("flutterView surfaceChanged"); public void onTrimMemory(int level) {
try { if (mFlutterEngine != null) {
mCallback.surfaceChanged(holder,format,width,height); if (level == 10) {
scheduleFrame(); mFlutterEngine.getSystemChannel().sendMemoryPressureWarning();
}catch (Throwable t){ }
Debuger.exception(t); } else {
Log.w("FlutterFragment", "onTrimMemory() invoked before FlutterFragment was attached to an Activity.");
} }
} }
@Override public void onLowMemory() {
public void surfaceDestroyed(SurfaceHolder holder) { mFlutterEngine.getSystemChannel().sendMemoryPressureWarning();
//Debuger.log("flutterView surfaceDestroyed"); }
try {
mCallback.surfaceDestroyed(holder); public static class Builder {
}catch (Throwable t){ private Context context;
Debuger.exception(t); private FlutterEngine engine;
private FlutterView.RenderMode renderMode;
private FlutterView.TransparencyMode transparencyMode;
public Builder(Context ctx) {
this.context = ctx;
renderMode = FlutterView.RenderMode.surface;
transparencyMode = FlutterView.TransparencyMode.transparent;
} }
public Builder flutterEngine(FlutterEngine engine) {
this.engine = engine;
return this;
} }
public Builder renderMode(FlutterView.RenderMode renderMode) {
this.renderMode = renderMode;
return this;
} }
@Override
protected void onAttachedToWindow() { public Builder transparencyMode(FlutterView.TransparencyMode transparencyMode) {
//Debuger.log("flutterView onAttachedToWindow"); this.transparencyMode = transparencyMode;
super.onAttachedToWindow(); return this;
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { }
// final WindowInsets windowInsets = getRootWindowInsets();
// if(windowInsets != null) { public BoostFlutterView build() {
// if(mCurrentWindowInsets == null || Bundle args = new Bundle();
// !TextUtils.equals(windowInsets.toString(),mCurrentWindowInsets.toString())) { args.putString("flutterview_render_mode", renderMode != null ? renderMode.name() : FlutterView.RenderMode.surface.name());
// Debuger.log("setWindowInsets "+windowInsets.toString()); args.putString("flutterview_transparency_mode", transparencyMode != null ? transparencyMode.name() : FlutterView.TransparencyMode.transparent.name());
//
// mCurrentWindowInsets = windowInsets; return new BoostFlutterView(context, engine, args);
// super.onApplyWindowInsets(mCurrentWindowInsets); }
// }
// }
// }else {
// ViewCompat.requestApplyInsets(this);
// }
ViewCompat.requestApplyInsets(this);
} }
} }
package com.taobao.idlefish.flutterboost;
import android.app.Activity;
import android.content.Context;
import io.flutter.app.FlutterPluginRegistry;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.platform.PlatformViewRegistry;
import io.flutter.view.FlutterView;
import io.flutter.view.TextureRegistry;
public class BoostPluginRegistry extends FlutterPluginRegistry {
private final FlutterEngine mEngine;
private final Activity mActivity;
public BoostPluginRegistry(FlutterEngine engine, Activity activity) {
super(engine, activity);
mEngine = engine;
mActivity = activity;
}
public PluginRegistry.Registrar registrarFor(String pluginKey) {
return new BoostRegistrar(mActivity,mEngine,super.registrarFor(pluginKey));
}
public static class BoostRegistrar implements PluginRegistry.Registrar {
private final PluginRegistry.Registrar mRegistrar;
private final FlutterEngine mEngine;
private final Activity mActivity;
BoostRegistrar(Activity activity, FlutterEngine engine, PluginRegistry.Registrar registrar) {
mRegistrar = registrar;
mEngine = engine;
mActivity = activity;
}
@Override
public Activity activity() {
return mActivity;
}
@Override
public Context context() {
return mRegistrar.context();
}
@Override
public Context activeContext() {
return mRegistrar.activeContext();
}
@Override
public BinaryMessenger messenger() {
return mEngine.getDartExecutor();
}
@Override
public TextureRegistry textures() {
return mEngine.getRenderer();
}
@Override
public PlatformViewRegistry platformViewRegistry() {
return mRegistrar.platformViewRegistry();
}
@Override
public FlutterView view() {
throw new RuntimeException("should not use!!!");
}
@Override
public String lookupKeyForAsset(String s) {
return mRegistrar.lookupKeyForAsset(s);
}
@Override
public String lookupKeyForAsset(String s, String s1) {
return mRegistrar.lookupKeyForAsset(s,s1);
}
@Override
public PluginRegistry.Registrar publish(Object o) {
return mRegistrar.publish(o);
}
@Override
public PluginRegistry.Registrar addRequestPermissionsResultListener(PluginRegistry.RequestPermissionsResultListener requestPermissionsResultListener) {
return mRegistrar.addRequestPermissionsResultListener(requestPermissionsResultListener);
}
@Override
public PluginRegistry.Registrar addActivityResultListener(PluginRegistry.ActivityResultListener activityResultListener) {
return mRegistrar.addActivityResultListener(activityResultListener);
}
@Override
public PluginRegistry.Registrar addNewIntentListener(PluginRegistry.NewIntentListener newIntentListener) {
return mRegistrar.addNewIntentListener(newIntentListener);
}
@Override
public PluginRegistry.Registrar addUserLeaveHintListener(PluginRegistry.UserLeaveHintListener userLeaveHintListener) {
return mRegistrar.addUserLeaveHintListener(userLeaveHintListener);
}
@Override
public PluginRegistry.Registrar addViewDestroyListener(PluginRegistry.ViewDestroyListener viewDestroyListener) {
return mRegistrar.addViewDestroyListener(viewDestroyListener);
}
}
}
...@@ -23,27 +23,26 @@ ...@@ -23,27 +23,26 @@
*/ */
package com.taobao.idlefish.flutterboost; package com.taobao.idlefish.flutterboost;
import android.os.Handler; import android.content.Intent;
import com.taobao.idlefish.flutterboost.NavigationService.NavigationService; import com.taobao.idlefish.flutterboost.NavigationService.NavigationService;
import com.taobao.idlefish.flutterboost.interfaces.IContainerManager;
import com.taobao.idlefish.flutterboost.interfaces.IContainerRecord; import com.taobao.idlefish.flutterboost.interfaces.IContainerRecord;
import com.taobao.idlefish.flutterboost.interfaces.IFlutterViewContainer; import com.taobao.idlefish.flutterboost.interfaces.IFlutterViewContainer;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import fleamarket.taobao.com.xservicekit.handler.MessageResult; import fleamarket.taobao.com.xservicekit.handler.MessageResult;
public class ContainerRecord implements IContainerRecord { public class ContainerRecord implements IContainerRecord {
private final IContainerManager mManager; private final FlutterViewContainerManager mManager;
private final IFlutterViewContainer mContainer; private final IFlutterViewContainer mContainer;
private final String mUniqueId; private final String mUniqueId;
private final Handler mHandler = new Handler();
private int mState = STATE_UNKNOW; private int mState = STATE_UNKNOW;
private MethodChannelProxy mProxy = new MethodChannelProxy(); private MethodChannelProxy mProxy = new MethodChannelProxy();
public ContainerRecord(IContainerManager manager, IFlutterViewContainer container) { ContainerRecord(FlutterViewContainerManager manager, IFlutterViewContainer container) {
mUniqueId = System.currentTimeMillis() + "-" + hashCode(); mUniqueId = System.currentTimeMillis() + "-" + hashCode();
mManager = manager; mManager = manager;
mContainer = container; mContainer = container;
...@@ -66,54 +65,119 @@ public class ContainerRecord implements IContainerRecord { ...@@ -66,54 +65,119 @@ public class ContainerRecord implements IContainerRecord {
@Override @Override
public void onCreate() { public void onCreate() {
Utils.assertCallOnMainThread();
if(mState != STATE_UNKNOW) {
Debuger.exception("state error");
}
mState = STATE_CREATED; mState = STATE_CREATED;
mContainer.getBoostFlutterView().boostResume(); mContainer.getBoostFlutterView().onResume();
mProxy.create(); mProxy.create();
} }
@Override @Override
public void onAppear() { public void onAppear() {
Utils.assertCallOnMainThread();
if(mState != STATE_CREATED && mState != STATE_DISAPPEAR) {
Debuger.exception("state error");
}
mState = STATE_APPEAR; mState = STATE_APPEAR;
mContainer.getBoostFlutterView().boostResume();
mManager.pushRecord(this);
mContainer.getBoostFlutterView().onAttach();
mProxy.appear(); mProxy.appear();
} }
@Override @Override
public void onDisappear() { public void onDisappear() {
mProxy.disappear(); Utils.assertCallOnMainThread();
if(mState != STATE_APPEAR) {
Debuger.exception("state error");
}
mState = STATE_DISAPPEAR; mState = STATE_DISAPPEAR;
/** mProxy.disappear();
* Bug workaround:
* If current container is finishing, we should call destroy flutter page early. mContainer.getBoostFlutterView().onDetach();
*/
if(mContainer.isFinishing()) { mManager.popRecord(this);
mHandler.post(new Runnable() { }
@Override @Override
public void run() { public void onDestroy() {
Utils.assertCallOnMainThread();
if(mState != STATE_DISAPPEAR) {
Debuger.exception("state error");
}
mState = STATE_DESTROYED;
mProxy.destroy(); mProxy.destroy();
mManager.removeRecord(this);
if(!mManager.hasContainerAppear()) {
mContainer.getBoostFlutterView().onPause();
mContainer.getBoostFlutterView().onStop();
} }
});
} }
@Override
public void onBackPressed() {
Utils.assertCallOnMainThread();
if(mState == STATE_UNKNOW || mState == STATE_DESTROYED) {
Debuger.exception("state error");
}
Map<String, String> map = new HashMap<>();
map.put("type", "backPressedCallback");
map.put("name", mContainer.getContainerName());
map.put("uniqueId", mUniqueId);
NavigationService.getService().emitEvent(map);
mContainer.getBoostFlutterView().onBackPressed();
} }
@Override @Override
public void onDestroy() { public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
mProxy.destroy(); mContainer.getBoostFlutterView().onRequestPermissionsResult(requestCode,permissions,grantResults);
mState = STATE_DESTROYED;
} }
@Override @Override
public void onResult(Map Result) { public void onNewIntent(Intent intent) {
NavigationService.onNativePageResult( mContainer.getBoostFlutterView().onNewIntent(intent);
genResult("onNativePageResult"),
mUniqueId,
mUniqueId,
Result,
mContainer.getContainerParams()
);
} }
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
mContainer.getBoostFlutterView().onActivityResult(requestCode,resultCode,data);
}
@Override
public void onUserLeaveHint() {
mContainer.getBoostFlutterView().onUserLeaveHint();
}
@Override
public void onTrimMemory(int level) {
mContainer.getBoostFlutterView().onTrimMemory(level);
}
@Override
public void onLowMemory() {
mContainer.getBoostFlutterView().onLowMemory();
}
private class MethodChannelProxy { private class MethodChannelProxy {
private int mState = STATE_UNKNOW; private int mState = STATE_UNKNOW;
......
...@@ -28,16 +28,14 @@ import android.app.Application; ...@@ -28,16 +28,14 @@ import android.app.Application;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.taobao.idlefish.flutterboost.NavigationService.NavigationService; import com.taobao.idlefish.flutterboost.NavigationService.NavigationService;
import com.taobao.idlefish.flutterboost.interfaces.IContainerRecord;
import com.taobao.idlefish.flutterboost.interfaces.IFlutterViewContainer; import com.taobao.idlefish.flutterboost.interfaces.IFlutterViewContainer;
import com.taobao.idlefish.flutterboost.loader.ServiceLoader; import com.taobao.idlefish.flutterboost.loader.ServiceLoader;
import com.taobao.idlefish.flutterboost.interfaces.IContainerManager; import com.taobao.idlefish.flutterboost.interfaces.IContainerManager;
import com.taobao.idlefish.flutterboost.interfaces.IFlutterViewProvider; import com.taobao.idlefish.flutterboost.interfaces.IFlutterEngineProvider;
import com.taobao.idlefish.flutterboost.interfaces.IPlatform; import com.taobao.idlefish.flutterboost.interfaces.IPlatform;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
...@@ -50,7 +48,6 @@ import fleamarket.taobao.com.xservicekit.handler.MessageResult; ...@@ -50,7 +48,6 @@ import fleamarket.taobao.com.xservicekit.handler.MessageResult;
import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.PluginRegistry; import io.flutter.plugin.common.PluginRegistry;
import io.flutter.view.FlutterView;
public class FlutterBoostPlugin implements MethodChannel.MethodCallHandler, Application.ActivityLifecycleCallbacks { public class FlutterBoostPlugin implements MethodChannel.MethodCallHandler, Application.ActivityLifecycleCallbacks {
...@@ -70,12 +67,12 @@ public class FlutterBoostPlugin implements MethodChannel.MethodCallHandler, Appl ...@@ -70,12 +67,12 @@ public class FlutterBoostPlugin implements MethodChannel.MethodCallHandler, Appl
channel.setMethodCallHandler(sInstance); channel.setMethodCallHandler(sInstance);
} }
public static IFlutterViewProvider viewProvider() { public static IFlutterEngineProvider engineProvider() {
if (sInstance == null) { if (sInstance == null) {
throw new RuntimeException("FlutterBoostPlugin not init yet"); throw new RuntimeException("FlutterBoostPlugin not init yet");
} }
return sInstance.mViewProvider; return BoostEngineProvider.sInstance;
} }
public static IContainerManager containerManager() { public static IContainerManager containerManager() {
...@@ -104,7 +101,6 @@ public class FlutterBoostPlugin implements MethodChannel.MethodCallHandler, Appl ...@@ -104,7 +101,6 @@ public class FlutterBoostPlugin implements MethodChannel.MethodCallHandler, Appl
private final IPlatform mPlatform; private final IPlatform mPlatform;
private final IContainerManager mManager; private final IContainerManager mManager;
private final IFlutterViewProvider mViewProvider;
private final PageResultMediator mMediator; private final PageResultMediator mMediator;
...@@ -112,7 +108,6 @@ public class FlutterBoostPlugin implements MethodChannel.MethodCallHandler, Appl ...@@ -112,7 +108,6 @@ public class FlutterBoostPlugin implements MethodChannel.MethodCallHandler, Appl
private FlutterBoostPlugin(IPlatform platform) { private FlutterBoostPlugin(IPlatform platform) {
mPlatform = platform; mPlatform = platform;
mViewProvider = new FlutterViewProvider(platform);
mManager = new FlutterViewContainerManager(); mManager = new FlutterViewContainerManager();
mMediator = new PageResultMediator(); mMediator = new PageResultMediator();
} }
...@@ -140,10 +135,6 @@ public class FlutterBoostPlugin implements MethodChannel.MethodCallHandler, Appl ...@@ -140,10 +135,6 @@ public class FlutterBoostPlugin implements MethodChannel.MethodCallHandler, Appl
ctx = currentActivity(); ctx = currentActivity();
} }
if (ctx == null) {
ctx = sInstance.mPlatform.getMainActivity();
}
if (ctx == null) { if (ctx == null) {
ctx = sInstance.mPlatform.getApplication(); ctx = sInstance.mPlatform.getApplication();
} }
...@@ -248,7 +239,7 @@ public class FlutterBoostPlugin implements MethodChannel.MethodCallHandler, Appl ...@@ -248,7 +239,7 @@ public class FlutterBoostPlugin implements MethodChannel.MethodCallHandler, Appl
if (mCurrentActiveActivity == null) { if (mCurrentActiveActivity == null) {
Debuger.log("Application entry foreground"); Debuger.log("Application entry foreground");
if (mViewProvider.tryGetFlutterView() != null) { if (BoostEngineProvider.sInstance.tryGetEngine() != null) {
Map<String, String> map = new HashMap<>(); Map<String, String> map = new HashMap<>();
map.put("type", "foreground"); map.put("type", "foreground");
NavigationService.getService().emitEvent(map); NavigationService.getService().emitEvent(map);
...@@ -272,7 +263,7 @@ public class FlutterBoostPlugin implements MethodChannel.MethodCallHandler, Appl ...@@ -272,7 +263,7 @@ public class FlutterBoostPlugin implements MethodChannel.MethodCallHandler, Appl
if (mCurrentActiveActivity == activity) { if (mCurrentActiveActivity == activity) {
Debuger.log("Application entry background"); Debuger.log("Application entry background");
if (mViewProvider.tryGetFlutterView() != null) { if (BoostEngineProvider.sInstance.tryGetEngine() != null) {
Map<String, String> map = new HashMap<>(); Map<String, String> map = new HashMap<>();
map.put("type", "background"); map.put("type", "background");
NavigationService.getService().emitEvent(map); NavigationService.getService().emitEvent(map);
...@@ -291,7 +282,7 @@ public class FlutterBoostPlugin implements MethodChannel.MethodCallHandler, Appl ...@@ -291,7 +282,7 @@ public class FlutterBoostPlugin implements MethodChannel.MethodCallHandler, Appl
if (mCurrentActiveActivity == activity) { if (mCurrentActiveActivity == activity) {
Debuger.log("Application entry background"); Debuger.log("Application entry background");
if (mViewProvider.tryGetFlutterView() != null) { if (BoostEngineProvider.sInstance.tryGetEngine() != null) {
Map<String, String> map = new HashMap<>(); Map<String, String> map = new HashMap<>();
map.put("type", "background"); map.put("type", "background");
NavigationService.getService().emitEvent(map); NavigationService.getService().emitEvent(map);
...@@ -321,15 +312,15 @@ public class FlutterBoostPlugin implements MethodChannel.MethodCallHandler, Appl ...@@ -321,15 +312,15 @@ public class FlutterBoostPlugin implements MethodChannel.MethodCallHandler, Appl
activity.setResult(Activity.RESULT_OK, intent); activity.setResult(Activity.RESULT_OK, intent);
} }
public static void onBoostResult(IFlutterViewContainer container, int requestCode, int resultCode, Intent intent) { // public static void onBoostResult(IFlutterViewContainer container, int requestCode, int resultCode, Intent intent) {
Map map = new HashMap(); // Map map = new HashMap();
if (intent != null) { // if (intent != null) {
map.put("result", intent.getSerializableExtra(IFlutterViewContainer.RESULT_KEY)); // map.put("result", intent.getSerializableExtra(IFlutterViewContainer.RESULT_KEY));
} // }
map.put("requestCode", requestCode); // map.put("requestCode", requestCode);
map.put("responseCode", resultCode); // map.put("responseCode", resultCode);
containerManager().onContainerResult(container, map); // containerManager().onContainerResult(container, map);
} // }
} }
...@@ -23,212 +23,89 @@ ...@@ -23,212 +23,89 @@
*/ */
package com.taobao.idlefish.flutterboost; package com.taobao.idlefish.flutterboost;
import android.app.Activity;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils; import android.text.TextUtils;
import com.taobao.idlefish.flutterboost.NavigationService.NavigationService;
import com.taobao.idlefish.flutterboost.interfaces.IContainerManager; import com.taobao.idlefish.flutterboost.interfaces.IContainerManager;
import com.taobao.idlefish.flutterboost.interfaces.IContainerRecord; import com.taobao.idlefish.flutterboost.interfaces.IContainerRecord;
import com.taobao.idlefish.flutterboost.interfaces.IFlutterViewContainer; import com.taobao.idlefish.flutterboost.interfaces.IFlutterViewContainer;
import com.taobao.idlefish.flutterboost.interfaces.IOperateSyncer;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.WeakHashMap; import java.util.Stack;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.view.FlutterMain;
import io.flutter.view.FlutterRunArguments;
public class FlutterViewContainerManager implements IContainerManager { public class FlutterViewContainerManager implements IContainerManager {
private final Map<IFlutterViewContainer, IContainerRecord> mRecords = new LinkedHashMap<>(); private final Map<IFlutterViewContainer, IContainerRecord> mRecordMap = new LinkedHashMap<>();
private final Instrument mInstrument;
private final Handler mHandler = new Handler(Looper.getMainLooper());
private final Set<ContainerRef> mRefs = new HashSet<>(); private final Set<ContainerRef> mRefs = new HashSet<>();
private final Stack<IContainerRecord> mRecordStack = new Stack<>();
private IContainerRecord mCurrentTopRecord; FlutterViewContainerManager() {}
FlutterViewContainerManager() {
mInstrument = new Instrument(this);
}
@Override @Override
public PluginRegistry onContainerCreate(IFlutterViewContainer container) { public IOperateSyncer generateSyncer(IFlutterViewContainer container) {
assertCallOnMainThread(); Utils.assertCallOnMainThread();
BoostEngineProvider.sInstance.createEngine(container.getContextActivity());
ContainerRecord record = new ContainerRecord(this, container); ContainerRecord record = new ContainerRecord(this, container);
if (mRecords.put(container, record) != null) { if (mRecordMap.put(container, record) != null) {
Debuger.exception("container:" + container.getContainerName() + " already exists!"); Debuger.exception("container:" + container.getContainerName() + " already exists!");
return new PluginRegistryImpl(container.getActivity(), container.getBoostFlutterView());
} }
mRefs.add(new ContainerRef(record.uniqueId(),container)); mRefs.add(new ContainerRef(record.uniqueId(),container));
FlutterMain.ensureInitializationComplete(container.getActivity().getApplicationContext(), null); return record;
BoostFlutterView flutterView = FlutterBoostPlugin.viewProvider().createFlutterView(container);
if (!flutterView.getFlutterNativeView().isApplicationRunning()) {
String appBundlePath = FlutterMain.findAppBundlePath(container.getActivity().getApplicationContext());
if (appBundlePath != null) {
FlutterRunArguments arguments = new FlutterRunArguments();
arguments.bundlePath = appBundlePath;
arguments.entrypoint = "main";
flutterView.runFromBundle(arguments);
}
}
mInstrument.performCreate(record);
return new PluginRegistryImpl(container.getActivity(), container.getBoostFlutterView());
}
@Override
public void onContainerAppear(IFlutterViewContainer container) {
assertCallOnMainThread();
final IContainerRecord record = mRecords.get(container);
if (record == null) {
Debuger.exception("container:" + container.getContainerName() + " not exists yet!");
return;
}
mInstrument.performAppear(record);
mCurrentTopRecord = record;
}
@Override
public void onContainerDisappear(IFlutterViewContainer container) {
assertCallOnMainThread();
final IContainerRecord record = mRecords.get(container);
if (record == null) {
Debuger.exception("container:" + container.getContainerName() + " not exists yet!");
return;
}
mInstrument.performDisappear(record);
if (!container.isFinishing()) {
checkIfFlutterViewNeedStopLater();
} }
}
@Override
public void onContainerDestroy(IFlutterViewContainer container) {
assertCallOnMainThread();
if (mCurrentTopRecord != null public void pushRecord(IContainerRecord record) {
&& mCurrentTopRecord.getContainer() == container) { if(!mRecordMap.containsValue(record)) {
mCurrentTopRecord = null; Debuger.exception("invalid record!");
} }
final IContainerRecord record = mRecords.remove(container); mRecordStack.push(record);
if (record == null) {
Debuger.exception("container:" + container.getContainerName() + " not exists yet!");
return;
} }
mInstrument.performDestroy(record); public void popRecord(IContainerRecord record) {
if(mRecordStack.peek() == record) {
checkIfFlutterViewNeedStopLater(); mRecordStack.pop();
}
private void checkIfFlutterViewNeedStopLater() {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (!hasContainerAppear()) {
FlutterBoostPlugin.viewProvider().stopFlutterView();
}
}
}, 250);
} }
@Override
public void onBackPressed(IFlutterViewContainer container) {
assertCallOnMainThread();
final IContainerRecord record = mRecords.get(container);
if (record == null) {
Debuger.exception("container:" + container.getContainerName() + " not exists yet!");
return;
} }
Map<String, String> map = new HashMap<>(); public void removeRecord(IContainerRecord record) {
map.put("type", "backPressedCallback"); mRecordStack.remove(record);
map.put("name", container.getContainerName()); mRecordMap.remove(record.getContainer());
map.put("uniqueId", record.uniqueId());
NavigationService.getService().emitEvent(map);
} }
@Override @Override
public void destroyContainerRecord(String name, String uniqueId) { public IFlutterViewContainer closeContainer(String uniqueId, Map<String, Object> result) {
assertCallOnMainThread(); for (Map.Entry<IFlutterViewContainer, IContainerRecord> entry : mRecordMap.entrySet()) {
boolean done = false;
for (Map.Entry<IFlutterViewContainer, IContainerRecord> entry : mRecords.entrySet()) {
if (TextUtils.equals(uniqueId, entry.getValue().uniqueId())) { if (TextUtils.equals(uniqueId, entry.getValue().uniqueId())) {
entry.getKey().destroyContainer(); entry.getKey().finishContainer();
done = true; return entry.getKey();
break;
} }
} }
if (!done) { Debuger.exception("closeContainer can not find uniqueId:" + uniqueId);
Debuger.exception("destroyContainerRecord can not find name:" + name + " uniqueId:" + uniqueId);
}
}
@Override return null;
public void onContainerResult(IFlutterViewContainer container, Map result) {
final IContainerRecord record = mRecords.get(container);
if (record == null) {
Debuger.exception("container:" + container.getContainerName() + " not exists yet!");
return;
}
record.onResult(result);
}
@Override
public void setContainerResult(String uniqueId, Map result) {
if (result == null) {
Debuger.exception("setContainerResult result is null");
return;
}
if (!(result instanceof HashMap)) {
result = new HashMap();
result.putAll(result);
}
boolean done = false;
for (Map.Entry<IFlutterViewContainer, IContainerRecord> entry : mRecords.entrySet()) {
if (TextUtils.equals(uniqueId, entry.getValue().uniqueId())) {
entry.getKey().setBoostResult((HashMap) result);
done = true;
break;
}
}
if (!done) {
Debuger.exception("setContainerResult can not find uniqueId:" + uniqueId);
}
} }
@Override @Override
public IContainerRecord getCurrentTopRecord() { public IContainerRecord getCurrentTopRecord() {
return mCurrentTopRecord; if(mRecordStack.isEmpty()) return null;
return mRecordStack.peek();
} }
@Override @Override
public IContainerRecord getLastRecord() { public IContainerRecord getLastGenerateRecord() {
final Collection<IContainerRecord> values = mRecords.values(); final Collection<IContainerRecord> values = mRecordMap.values();
if(!values.isEmpty()) { if(!values.isEmpty()) {
final ArrayList<IContainerRecord> array = new ArrayList<>(values); final ArrayList<IContainerRecord> array = new ArrayList<>(values);
return array.get(array.size()-1); return array.get(array.size()-1);
...@@ -239,7 +116,7 @@ public class FlutterViewContainerManager implements IContainerManager { ...@@ -239,7 +116,7 @@ public class FlutterViewContainerManager implements IContainerManager {
@Override @Override
public IFlutterViewContainer findContainerById(String uniqueId) { public IFlutterViewContainer findContainerById(String uniqueId) {
IFlutterViewContainer target = null; IFlutterViewContainer target = null;
for (Map.Entry<IFlutterViewContainer, IContainerRecord> entry : mRecords.entrySet()) { for (Map.Entry<IFlutterViewContainer, IContainerRecord> entry : mRecordMap.entrySet()) {
if (TextUtils.equals(uniqueId, entry.getValue().uniqueId())) { if (TextUtils.equals(uniqueId, entry.getValue().uniqueId())) {
target = entry.getKey(); target = entry.getKey();
break; break;
...@@ -259,12 +136,12 @@ public class FlutterViewContainerManager implements IContainerManager { ...@@ -259,12 +136,12 @@ public class FlutterViewContainerManager implements IContainerManager {
@Override @Override
public void onShownContainerChanged(String old, String now) { public void onShownContainerChanged(String old, String now) {
assertCallOnMainThread(); Utils.assertCallOnMainThread();
IFlutterViewContainer oldContainer = null; IFlutterViewContainer oldContainer = null;
IFlutterViewContainer nowContainer = null; IFlutterViewContainer nowContainer = null;
for (Map.Entry<IFlutterViewContainer, IContainerRecord> entry : mRecords.entrySet()) { for (Map.Entry<IFlutterViewContainer, IContainerRecord> entry : mRecordMap.entrySet()) {
if (TextUtils.equals(old, entry.getValue().uniqueId())) { if (TextUtils.equals(old, entry.getValue().uniqueId())) {
oldContainer = entry.getKey(); oldContainer = entry.getKey();
} }
...@@ -289,9 +166,7 @@ public class FlutterViewContainerManager implements IContainerManager { ...@@ -289,9 +166,7 @@ public class FlutterViewContainerManager implements IContainerManager {
@Override @Override
public boolean hasContainerAppear() { public boolean hasContainerAppear() {
assertCallOnMainThread(); for (Map.Entry<IFlutterViewContainer, IContainerRecord> entry : mRecordMap.entrySet()) {
for (Map.Entry<IFlutterViewContainer, IContainerRecord> entry : mRecords.entrySet()) {
if (entry.getValue().getState() == IContainerRecord.STATE_APPEAR) { if (entry.getValue().getState() == IContainerRecord.STATE_APPEAR) {
return true; return true;
} }
...@@ -300,15 +175,6 @@ public class FlutterViewContainerManager implements IContainerManager { ...@@ -300,15 +175,6 @@ public class FlutterViewContainerManager implements IContainerManager {
return false; return false;
} }
@Override
public void reset() {
}
private void assertCallOnMainThread() {
if (Looper.myLooper() != Looper.getMainLooper()) {
Debuger.exception("must call method on main thread");
}
}
public static class ContainerRef { public static class ContainerRef {
public final String uniqueId; public final String uniqueId;
...@@ -319,28 +185,4 @@ public class FlutterViewContainerManager implements IContainerManager { ...@@ -319,28 +185,4 @@ public class FlutterViewContainerManager implements IContainerManager {
this.container = new WeakReference<>(container); this.container = new WeakReference<>(container);
} }
} }
public static class PluginRegistryImpl implements PluginRegistry {
final BoostFlutterView mBoostFlutterView;
PluginRegistryImpl(Activity activity, BoostFlutterView flutterView) {
mBoostFlutterView = flutterView;
}
@Override
public Registrar registrarFor(String pluginKey) {
return mBoostFlutterView.getPluginRegistry().registrarFor(pluginKey);
}
@Override
public boolean hasPlugin(String key) {
return mBoostFlutterView.getPluginRegistry().hasPlugin(key);
}
@Override
public <T> T valuePublishedByPlugin(String pluginKey) {
return mBoostFlutterView.getPluginRegistry().valuePublishedByPlugin(pluginKey);
}
}
} }
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost;
import com.taobao.idlefish.flutterboost.interfaces.IContainerRecord;
import com.taobao.idlefish.flutterboost.interfaces.IContainerManager;
public class Instrument {
private final IContainerManager mManager;
Instrument(IContainerManager manager) {
mManager = manager;
}
public void performCreate(IContainerRecord record) {
final int currentState = record.getState();
if (currentState != IContainerRecord.STATE_UNKNOW) {
Debuger.exception("performCreate state error, current state:" + currentState);
return;
}
record.onCreate();
}
public void performAppear(IContainerRecord record) {
final int currentState = record.getState();
if (currentState != IContainerRecord.STATE_CREATED
&& currentState != IContainerRecord.STATE_DISAPPEAR) {
Debuger.exception("performAppear state error, current state:" + currentState);
return;
}
record.onAppear();
}
public void performDisappear(IContainerRecord record) {
final int currentState = record.getState();
if (currentState != IContainerRecord.STATE_APPEAR) {
Debuger.exception("performDisappear state error , current state:" + currentState);
return;
}
record.onDisappear();
}
public void performDestroy(IContainerRecord record) {
final int currentState = record.getState();
if (currentState != IContainerRecord.STATE_DISAPPEAR) {
Debuger.exception("performDestroy state error, current state:" + currentState);
}
record.onDestroy();
}
}
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
private boolean onCall(MessageResult<Boolean> result,String uniqueId,String pageName,Map params,Boolean animated){ private boolean onCall(MessageResult<Boolean> result,String uniqueId,String pageName,Map params,Boolean animated){
FlutterBoostPlugin.containerManager().destroyContainerRecord(pageName,uniqueId); FlutterBoostPlugin.containerManager().closeContainer(uniqueId,null);
result.success(true); result.success(true);
return true; return true;
} }
......
...@@ -38,8 +38,8 @@ ...@@ -38,8 +38,8 @@
private boolean onCall(MessageResult<Boolean> result,String uniqueId,String key,Map resultData,Map params){ private boolean onCall(MessageResult<Boolean> result,String uniqueId,String key,Map resultData,Map params){
FlutterBoostPlugin.containerManager().setContainerResult(uniqueId,resultData); // FlutterBoostPlugin.containerManager().setContainerResult(uniqueId,resultData);
result.success(true); // result.success(true);
return true; return true;
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
import com.taobao.idlefish.flutterboost.FlutterBoostPlugin; import com.taobao.idlefish.flutterboost.FlutterBoostPlugin;
import com.taobao.idlefish.flutterboost.FlutterViewContainerManager; import com.taobao.idlefish.flutterboost.FlutterViewContainerManager;
import com.taobao.idlefish.flutterboost.interfaces.IContainerRecord; import com.taobao.idlefish.flutterboost.interfaces.IContainerRecord;
import com.taobao.idlefish.flutterboost.interfaces.IFlutterViewContainer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
...@@ -47,7 +48,7 @@ ...@@ -47,7 +48,7 @@
.containerManager().getCurrentTopRecord(); .containerManager().getCurrentTopRecord();
if(record == null) { if(record == null) {
record = FlutterBoostPlugin.containerManager().getLastRecord(); record = FlutterBoostPlugin.containerManager().getLastGenerateRecord();
} }
pageInfo.put("name",record.getContainer().getContainerName()); pageInfo.put("name",record.getContainer().getContainerName());
......
...@@ -25,9 +25,16 @@ package com.taobao.idlefish.flutterboost; ...@@ -25,9 +25,16 @@ package com.taobao.idlefish.flutterboost;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Color; import android.graphics.Color;
import android.os.Looper;
public class Utils { public class Utils {
public static void assertCallOnMainThread() {
if (Looper.myLooper() != Looper.getMainLooper()) {
Debuger.exception("must call method on main thread");
}
}
public static boolean checkImageValid(final Bitmap bitmap) { public static boolean checkImageValid(final Bitmap bitmap) {
if (null == bitmap) { if (null == bitmap) {
return false; return false;
......
...@@ -24,161 +24,123 @@ ...@@ -24,161 +24,123 @@
package com.taobao.idlefish.flutterboost.containers; package com.taobao.idlefish.flutterboost.containers;
import android.app.Activity; import android.app.Activity;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle; import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import com.taobao.idlefish.flutterboost.BoostFlutterView; import com.taobao.idlefish.flutterboost.BoostFlutterView;
import com.taobao.idlefish.flutterboost.FlutterBoostPlugin; import com.taobao.idlefish.flutterboost.FlutterBoostPlugin;
import com.taobao.idlefish.flutterboost.interfaces.IFlutterViewContainer; import com.taobao.idlefish.flutterboost.interfaces.IFlutterViewContainer;
import com.taobao.idlefish.flutterboost.interfaces.IOperateSyncer;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
import io.flutter.app.FlutterActivity; import io.flutter.embedding.android.FlutterView;
import io.flutter.view.FlutterNativeView;
import io.flutter.view.FlutterView;
abstract public class BoostFlutterActivity extends FlutterActivity implements IFlutterViewContainer { public abstract class BoostFlutterActivity extends Activity implements IFlutterViewContainer {
private FlutterContent mFlutterContent; private BoostFlutterView mFlutterView;
private IOperateSyncer mSyncer;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mFlutterContent = new FlutterContent(this); BoostFlutterView.Builder builder = new BoostFlutterView.Builder(this);
mFlutterView = builder.renderMode(FlutterView.RenderMode.texture)
.transparencyMode(FlutterView.TransparencyMode.opaque)
.build();
setContentView(mFlutterContent); setContentView(mFlutterView);
FlutterBoostPlugin.containerManager().onContainerCreate(this); mSyncer = FlutterBoostPlugin.containerManager().generateSyncer(this);
onRegisterPlugins(this); mSyncer.onCreate();
} }
@Override @Override
protected void onPostResume() { protected void onResume() {
super.onPostResume(); super.onResume();
FlutterBoostPlugin.containerManager().onContainerAppear(BoostFlutterActivity.this); mSyncer.onAppear();
mFlutterContent.attachFlutterView(getBoostFlutterView());
} }
@Override @Override
protected void onPause() { protected void onPause() {
mFlutterContent.detachFlutterView(); mSyncer.onDisappear();
FlutterBoostPlugin.containerManager().onContainerDisappear(this);
super.onPause(); super.onPause();
} }
@Override @Override
protected void onDestroy() { protected void onDestroy() {
FlutterBoostPlugin.containerManager().onContainerDestroy(this); mSyncer.onDestroy();
mFlutterContent.destroy();
super.onDestroy(); super.onDestroy();
} }
public FlutterView createFlutterView(Context context) {
return FlutterBoostPlugin.viewProvider().createFlutterView(this);
}
@Override @Override
public FlutterNativeView createFlutterNativeView() { public void onBackPressed() {
return FlutterBoostPlugin.viewProvider().createFlutterNativeView(this); super.onBackPressed();
mSyncer.onBackPressed();
} }
@Override @Override
public boolean retainFlutterNativeView() { protected void onNewIntent(Intent intent) {
return true; super.onNewIntent(intent);
mSyncer.onNewIntent(intent);
} }
protected View createSplashScreenView() { @Override
FrameLayout frameLayout = new FrameLayout(this); protected void onActivityResult(int requestCode, int resultCode, Intent data) {
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( super.onActivityResult(requestCode, resultCode, data);
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); mSyncer.onActivityResult(requestCode,resultCode,data);
params.gravity = Gravity.CENTER;
frameLayout.addView(new ProgressBar(this), params);
return frameLayout;
} }
protected View createFlutterInitCoverView() { @Override
View initCover = new View(this); public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
initCover.setBackgroundColor(Color.WHITE); super.onRequestPermissionsResult(requestCode, permissions, grantResults);
return initCover; mSyncer.onRequestPermissionsResult(requestCode, permissions, grantResults);
} }
@Override @Override
public void onContainerShown() { public void onTrimMemory(int level) {
mFlutterContent.onContainerShown(); super.onTrimMemory(level);
mSyncer.onTrimMemory(level);
} }
@Override @Override
public void onContainerHidden() { public void onLowMemory() {
mFlutterContent.onContainerHidden(); super.onLowMemory();
mSyncer.onLowMemory();
} }
@Override @Override
public void onBackPressed() { protected void onUserLeaveHint() {
FlutterBoostPlugin.containerManager().onBackPressed(this); super.onUserLeaveHint();
mSyncer.onUserLeaveHint();
} }
@Override @Override
public Activity getActivity() { public Activity getContextActivity() {
return this; return this;
} }
@Override @Override
public BoostFlutterView getBoostFlutterView() { public BoostFlutterView getBoostFlutterView() {
return (BoostFlutterView) getFlutterView(); return mFlutterView;
} }
@Override @Override
public void destroyContainer() { public void finishContainer() {
finish(); finish();
} }
@Override @Override
public abstract String getContainerName(); public void onContainerShown() {}
@Override @Override
public abstract Map getContainerParams(); public void onContainerHidden() {}
@Override @Override
public void setBoostResult(HashMap result) { public void setBoostResult(HashMap result) {
FlutterBoostPlugin.setBoostResult(this, result); Intent data = new Intent();
} data.putExtra(RESULT_KEY,result);
setResult(RESULT_OK,data);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
FlutterBoostPlugin.onBoostResult(this,requestCode,resultCode,data);
}
class FlutterContent extends FlutterViewStub {
public FlutterContent(Context context) {
super(context);
}
@Override
public View createFlutterInitCoverView() {
return BoostFlutterActivity.this.createFlutterInitCoverView();
}
@Override
public BoostFlutterView getBoostFlutterView() {
return BoostFlutterActivity.this.getBoostFlutterView();
}
@Override
public View createSplashScreenView() {
return BoostFlutterActivity.this.createSplashScreenView();
}
} }
} }
...@@ -23,138 +23,120 @@ ...@@ -23,138 +23,120 @@
*/ */
package com.taobao.idlefish.flutterboost.containers; package com.taobao.idlefish.flutterboost.containers;
import android.content.Context; import android.app.Activity;
import android.graphics.Color; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import com.taobao.idlefish.flutterboost.BoostFlutterView; import com.taobao.idlefish.flutterboost.BoostFlutterView;
import com.taobao.idlefish.flutterboost.Debuger;
import com.taobao.idlefish.flutterboost.FlutterBoostPlugin; import com.taobao.idlefish.flutterboost.FlutterBoostPlugin;
import com.taobao.idlefish.flutterboost.interfaces.IFlutterViewContainer; import com.taobao.idlefish.flutterboost.interfaces.IFlutterViewContainer;
import com.taobao.idlefish.flutterboost.interfaces.IOperateSyncer;
import java.util.HashMap; import java.util.HashMap;
import io.flutter.plugin.common.PluginRegistry; import io.flutter.embedding.android.FlutterView;
abstract public class BoostFlutterFragment extends Fragment implements IFlutterViewContainer { abstract public class BoostFlutterFragment extends Fragment implements IFlutterViewContainer {
FlutterContent mContent; private BoostFlutterView mFlutterView;
PluginRegistry mRegistry; private IOperateSyncer mSyncer;
boolean resumed = false;
@Nullable
@Override @Override
public void onCreate(Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); BoostFlutterView.Builder builder = new BoostFlutterView.Builder(getContextActivity());
mFlutterView = builder.renderMode(FlutterView.RenderMode.texture)
.transparencyMode(FlutterView.TransparencyMode.opaque)
.build();
mRegistry = FlutterBoostPlugin.containerManager().onContainerCreate(this); mSyncer = FlutterBoostPlugin.containerManager().generateSyncer(this);
onRegisterPlugins(mRegistry); mSyncer.onCreate();
}
@Override return mFlutterView;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
mContent = new FlutterContent(getActivity());
return mContent;
} }
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
if (!resumed) { mSyncer.onAppear();
resumed = true;
FlutterBoostPlugin.containerManager().onContainerAppear(this);
mContent.attachFlutterView(getBoostFlutterView());
Log.e("FlutterBoost", "FlutterMenuFragment resume");
}
} }
@Override @Override
public void onPause() { public void onPause() {
mSyncer.onDisappear();
super.onPause(); super.onPause();
if (resumed) {
resumed = false;
mContent.snapshot();
FlutterBoostPlugin.containerManager().onContainerDisappear(this);
Log.e("FlutterBoost", "FlutterMenuFragment stop");
}
} }
@Override @Override
public void onDestroy() { public void onDestroy() {
mSyncer.onDestroy();
super.onDestroy(); super.onDestroy();
if (mContent != null) {
mContent.destroy();
}
FlutterBoostPlugin.containerManager().onContainerDestroy(this);
} }
@Override public void onBackPressed() {
public void onContainerShown() { mSyncer.onBackPressed();
mContent.onContainerShown();
} }
@Override public void onNewIntent(Intent intent) {
public void onContainerHidden() { mSyncer.onNewIntent(intent);
mContent.onContainerHidden();
} }
@Override @Override
public BoostFlutterView getBoostFlutterView() { public void onActivityResult(int requestCode, int resultCode, Intent data) {
return FlutterBoostPlugin.viewProvider().createFlutterView(this); super.onActivityResult(requestCode, resultCode, data);
mSyncer.onActivityResult(requestCode,resultCode,data);
} }
@Override @Override
public boolean isFinishing() { public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
return getActivity().isFinishing(); super.onRequestPermissionsResult(requestCode, permissions, grantResults);
} mSyncer.onRequestPermissionsResult(requestCode, permissions, grantResults);
protected View createSplashScreenView() {
FrameLayout layout = new FrameLayout(getContext());
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.CENTER;
layout.addView(new ProgressBar(getContext()),params);
return layout;
} }
protected View createFlutterInitCoverView() { public void onTrimMemory(int level) {
View initCover = new View(getActivity()); mSyncer.onTrimMemory(level);
initCover.setBackgroundColor(Color.WHITE);
return initCover;
} }
@Override @Override
public void setBoostResult(HashMap result) { public void onLowMemory() {
super.onLowMemory();
mSyncer.onLowMemory();
} }
class FlutterContent extends FlutterViewStub { public void onUserLeaveHint() {
mSyncer.onUserLeaveHint();
public FlutterContent(Context context) {
super(context);
} }
@Override @Override
public View createFlutterInitCoverView() { public Activity getContextActivity() {
return BoostFlutterFragment.this.createFlutterInitCoverView(); return getActivity();
} }
@Override @Override
public BoostFlutterView getBoostFlutterView() { public BoostFlutterView getBoostFlutterView() {
return BoostFlutterFragment.this.getBoostFlutterView(); return mFlutterView;
} }
@Override @Override
public View createSplashScreenView() { public void finishContainer() {
return BoostFlutterFragment.this.createSplashScreenView(); getActivity().finish();
} }
@Override
public void onContainerShown() {}
@Override
public void onContainerHidden() {}
@Override
public void setBoostResult(HashMap result) {
Intent data = new Intent();
data.putExtra(RESULT_KEY,result);
getActivity().setResult(Activity.RESULT_OK,data);
} }
} }
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost.containers;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import com.taobao.idlefish.flutterboost.BoostFlutterView;
import com.taobao.idlefish.flutterboost.Debuger;
abstract public class FlutterViewStub extends FrameLayout {
public static final Handler sHandler = new ProcessHandler(Looper.getMainLooper());
protected Bitmap mBitmap;
protected ImageView mSnapshot;
protected FrameLayout mStub;
protected View mCover;
protected View mSplashScreenView;
public FlutterViewStub(Context context) {
super(context);
mStub = new FrameLayout(context);
mStub.setBackgroundColor(Color.WHITE);
addView(mStub, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
mSnapshot = new ImageView(context);
mSnapshot.setScaleType(ImageView.ScaleType.FIT_CENTER);
mSnapshot.setLayoutParams(new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
mCover = createFlutterInitCoverView();
addView(mCover, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
final BoostFlutterView flutterView = getBoostFlutterView();
if (!flutterView.firstFrameCalled()) {
mSplashScreenView = createSplashScreenView();
addView(mSplashScreenView, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
}
}
public void onContainerShown() {
Debuger.log("onContainerShown");
sHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (mSplashScreenView != null) {
FlutterViewStub.this.removeView(mSplashScreenView);
mSplashScreenView = null;
}
if (mCover != null) {
FlutterViewStub.this.removeView(mCover);
}
if (mSnapshot.getParent() == FlutterViewStub.this) {
FlutterViewStub.this.removeView(mSnapshot);
mSnapshot.setImageBitmap(null);
if (mBitmap != null && !mBitmap.isRecycled()) {
mBitmap.recycle();
mBitmap = null;
}
}
getBoostFlutterView().scheduleFrame();
getBoostFlutterView().requestFocus();
getBoostFlutterView().invalidate();
}
}, 167);
}
public void onContainerHidden() {
//Debuger.log("onContainerHidden");
}
public void snapshot() {
if (mStub.getChildCount() <= 0) return;
if (mSnapshot.getParent() != null) return;
BoostFlutterView flutterView = (BoostFlutterView) mStub.getChildAt(0);
mBitmap = flutterView.getBitmap();
if (mBitmap != null && !mBitmap.isRecycled()) {
mSnapshot.setImageBitmap(mBitmap);
addView(mSnapshot);
}
}
public void attachFlutterView(final BoostFlutterView flutterView) {
if (flutterView.getParent() != mStub) {
sHandler.removeMessages(ProcessHandler.MSG_DETACH);
Debuger.log("attachFlutterView");
if (flutterView.getParent() != null) {
((ViewGroup) flutterView.getParent()).removeView(flutterView);
}
mStub.addView(flutterView, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
}
}
public void detachFlutterView() {
if (mStub.getChildCount() <= 0) return;
final BoostFlutterView flutterView = (BoostFlutterView) mStub.getChildAt(0);
if (flutterView == null) return;
if (mSnapshot.getParent() == null) {
mBitmap = flutterView.getBitmap();
if (mBitmap != null && !mBitmap.isRecycled()) {
mSnapshot.setImageBitmap(mBitmap);
Debuger.log("snapshot view");
addView(mSnapshot);
}
}
Message msg = new Message();
msg.what = ProcessHandler.MSG_DETACH;
msg.obj = new Runnable() {
@Override
public void run() {
if (flutterView.getParent() != null && flutterView.getParent() == mStub) {
Debuger.log("detachFlutterView");
mStub.removeView(flutterView);
}
}
};
sHandler.sendMessageDelayed(msg,18);
}
public void destroy() {
removeAllViews();
mSnapshot.setImageBitmap(null);
if (mBitmap != null && !mBitmap.isRecycled()) {
mBitmap.recycle();
mBitmap = null;
}
}
protected View createFlutterInitCoverView() {
View initCover = new View(getContext());
initCover.setBackgroundColor(Color.WHITE);
return initCover;
}
protected View createSplashScreenView() {
FrameLayout layout = new FrameLayout(getContext());
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.CENTER;
layout.addView(new ProgressBar(getContext()),params);
return layout;
}
abstract protected BoostFlutterView getBoostFlutterView();
public static class ProcessHandler extends Handler {
static final int MSG_DETACH = 175101;
ProcessHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.obj instanceof Runnable) {
Runnable run = (Runnable) msg.obj;
run.run();
}
}
}
}
...@@ -23,106 +23,21 @@ ...@@ -23,106 +23,21 @@
*/ */
package com.taobao.idlefish.flutterboost.interfaces; package com.taobao.idlefish.flutterboost.interfaces;
import android.app.Activity;
import java.util.Map; import java.util.Map;
import io.flutter.plugin.common.PluginRegistry;
public interface IContainerManager { public interface IContainerManager {
/** IOperateSyncer generateSyncer(IFlutterViewContainer container);
* call by native side when container create
* @param container
* @return
*/
PluginRegistry onContainerCreate(IFlutterViewContainer container);
/** IFlutterViewContainer closeContainer(String uniqueId,Map<String,Object> result);
* call by native side when container appear
* @param container
* @return
*/
void onContainerAppear(IFlutterViewContainer container);
/**
* call by native side when container disappear
* @param container
* @return
*/
void onContainerDisappear(IFlutterViewContainer container);
/**
* call by native side when container destroy
* @param container
* @return
*/
void onContainerDestroy(IFlutterViewContainer container);
/**
* call by native side when back key pressed
* @param container
* @return
*/
void onBackPressed(IFlutterViewContainer container);
/**
* call by flutter side when need destroy container
* @param name
* @param uq
*/
void destroyContainerRecord(String name,String uq);
/**
* call by native side when container handle a result (onActivityResult)
* @param container
* @param result
*/
void onContainerResult(IFlutterViewContainer container,Map result);
/**
* call by flutter side when flutter want set a result for request (setResult)
* @param uniqueId
* @param result
*/
void setContainerResult(String uniqueId,Map result);
/**
* get current interactive container
* @return
*/
IContainerRecord getCurrentTopRecord(); IContainerRecord getCurrentTopRecord();
/** IContainerRecord getLastGenerateRecord();
* get last created container
* @return
*/
IContainerRecord getLastRecord();
/**
* find a container
* @param uniqueId
* @return
*/
IFlutterViewContainer findContainerById(String uniqueId); IFlutterViewContainer findContainerById(String uniqueId);
/** void onShownContainerChanged(String oldUniqueId,String nowUniqueId);
* call by flutter side when a container shown or hidden
* @param old
* @param now
*/
void onShownContainerChanged(String old,String now);
/**
* is any container appear now
* @return
*/
boolean hasContainerAppear(); boolean hasContainerAppear();
/**
* no use
*/
void reset();
} }
...@@ -23,12 +23,10 @@ ...@@ -23,12 +23,10 @@
*/ */
package com.taobao.idlefish.flutterboost.interfaces; package com.taobao.idlefish.flutterboost.interfaces;
import java.util.Map;
/** /**
* a container record, which use map a flutter page * a container record, which use map a flutter page
*/ */
public interface IContainerRecord { public interface IContainerRecord extends IOperateSyncer{
int STATE_UNKNOW = 0; int STATE_UNKNOW = 0;
int STATE_CREATED = 1; int STATE_CREATED = 1;
int STATE_APPEAR = 2; int STATE_APPEAR = 2;
...@@ -38,9 +36,4 @@ public interface IContainerRecord { ...@@ -38,9 +36,4 @@ public interface IContainerRecord {
String uniqueId(); String uniqueId();
IFlutterViewContainer getContainer(); IFlutterViewContainer getContainer();
int getState(); int getState();
void onCreate();
void onAppear();
void onDisappear();
void onDestroy();
void onResult(Map Result);
} }
...@@ -21,32 +21,31 @@ ...@@ -21,32 +21,31 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
package com.taobao.idlefish.flutterboost; package com.taobao.idlefish.flutterboost.interfaces;
import android.content.Context; import android.content.Context;
import io.flutter.view.FlutterNativeView; import com.taobao.idlefish.flutterboost.BoostFlutterView;
public class BoostFlutterNativeView extends FlutterNativeView { import io.flutter.embedding.engine.FlutterEngine;
public BoostFlutterNativeView(Context context) { /**
super(context); * a flutter view provider
} */
public interface IFlutterEngineProvider {
public void detachFromFlutterView() { /**
//do nothing... * create flutter engine, we just hold a single instance now
} * @param context
* @return
*/
FlutterEngine createEngine(Context context);
public void detach() { /**
//do nothing... * may return null
} * @return
*/
FlutterEngine tryGetEngine();
@Override
public void destroy() {
//do nothing...
}
public void boostDestroy() {
super.destroy();
}
} }
...@@ -37,7 +37,7 @@ import io.flutter.plugin.common.PluginRegistry; ...@@ -37,7 +37,7 @@ import io.flutter.plugin.common.PluginRegistry;
public interface IFlutterViewContainer { public interface IFlutterViewContainer {
String RESULT_KEY = "_flutter_result_"; String RESULT_KEY = "_flutter_result_";
Activity getActivity(); Activity getContextActivity();
/** /**
* provide a flutter view * provide a flutter view
...@@ -48,7 +48,7 @@ public interface IFlutterViewContainer { ...@@ -48,7 +48,7 @@ public interface IFlutterViewContainer {
/** /**
* call to destroy the container * call to destroy the container
*/ */
void destroyContainer(); void finishContainer();
/** /**
* container name * container name
...@@ -72,21 +72,9 @@ public interface IFlutterViewContainer { ...@@ -72,21 +72,9 @@ public interface IFlutterViewContainer {
*/ */
void onContainerHidden(); void onContainerHidden();
/**
* is container finishing
* @return
*/
boolean isFinishing();
/** /**
* call by flutter side to set result * call by flutter side to set result
* @param result * @param result
*/ */
void setBoostResult(HashMap result); void setBoostResult(HashMap result);
/**
* register flutter plugins
* @param registry
*/
void onRegisterPlugins(PluginRegistry registry);
} }
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost.interfaces;
import com.taobao.idlefish.flutterboost.BoostFlutterNativeView;
import com.taobao.idlefish.flutterboost.BoostFlutterView;
/**
* a flutter view provider
*/
public interface IFlutterViewProvider {
/**
* create flutter view, we just hold a single instance now
* @param container
* @return
*/
BoostFlutterView createFlutterView(IFlutterViewContainer container);
/**
* single instance also
* @param container
* @return
*/
BoostFlutterNativeView createFlutterNativeView(IFlutterViewContainer container);
/**
* may return null
* @return
*/
BoostFlutterView tryGetFlutterView();
/**
* release flutter view
*/
void stopFlutterView();
/**
* reset all refrence
*/
void reset();
}
package com.taobao.idlefish.flutterboost.interfaces;
import android.content.Intent;
public interface IOperateSyncer {
void onCreate();
void onAppear();
void onDisappear();
void onDestroy();
void onBackPressed();
void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults);
void onNewIntent(Intent intent);
void onActivityResult(int requestCode, int resultCode, Intent data);
void onUserLeaveHint();
void onTrimMemory(int level);
void onLowMemory();
}
...@@ -29,6 +29,8 @@ import android.content.Context; ...@@ -29,6 +29,8 @@ import android.content.Context;
import java.util.Map; import java.util.Map;
import io.flutter.plugin.common.PluginRegistry;
/** /**
* APIs that platform(Android App) must provide * APIs that platform(Android App) must provide
*/ */
...@@ -41,10 +43,10 @@ public interface IPlatform { ...@@ -41,10 +43,10 @@ public interface IPlatform {
Application getApplication(); Application getApplication();
/** /**
* get main activity, which must always exist at the bottom of task stack. * register plugins
* @return * @return
*/ */
Activity getMainActivity(); void onRegisterPlugins(PluginRegistry registry);
/** /**
* debug or not * debug or not
......
...@@ -28,11 +28,6 @@ public class FlutterFragment extends BoostFlutterFragment { ...@@ -28,11 +28,6 @@ public class FlutterFragment extends BoostFlutterFragment {
super.setArguments(args); super.setArguments(args);
} }
@Override
public void onRegisterPlugins(PluginRegistry registry) {
GeneratedPluginRegistrant.registerWith(registry);
}
@Override @Override
public String getContainerName() { public String getContainerName() {
return "flutterFragment"; return "flutterFragment";
...@@ -45,11 +40,6 @@ public class FlutterFragment extends BoostFlutterFragment { ...@@ -45,11 +40,6 @@ public class FlutterFragment extends BoostFlutterFragment {
return params; return params;
} }
@Override
public void destroyContainer() {
}
public static FlutterFragment instance(String tag){ public static FlutterFragment instance(String tag){
FlutterFragment fragment = new FlutterFragment(); FlutterFragment fragment = new FlutterFragment();
fragment.setTabTag(tag); fragment.setTabTag(tag);
......
...@@ -10,11 +10,6 @@ import io.flutter.plugins.GeneratedPluginRegistrant; ...@@ -10,11 +10,6 @@ import io.flutter.plugins.GeneratedPluginRegistrant;
public class FlutterPageActivity extends BoostFlutterActivity { public class FlutterPageActivity extends BoostFlutterActivity {
@Override
public void onRegisterPlugins(PluginRegistry registry) {
GeneratedPluginRegistrant.registerWith(registry);
}
/** /**
* 该方法返回当前Activity在Flutter层对应的name, * 该方法返回当前Activity在Flutter层对应的name,
* 混合栈将会在flutter层根据这个名字,在注册的Route表中查找对应的Widget * 混合栈将会在flutter层根据这个名字,在注册的Route表中查找对应的Widget
......
package com.taobao.idlefish.flutterboostexample; package com.taobao.idlefish.flutterboostexample;
import android.app.Activity;
import android.app.Application; import android.app.Application;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import com.taobao.idlefish.flutterboost.Debuger; import com.taobao.idlefish.flutterboost.Debuger;
import com.taobao.idlefish.flutterboost.FlutterBoostPlugin; import com.taobao.idlefish.flutterboost.FlutterBoostPlugin;
...@@ -13,6 +10,8 @@ import com.taobao.idlefish.flutterboost.interfaces.IPlatform; ...@@ -13,6 +10,8 @@ import com.taobao.idlefish.flutterboost.interfaces.IPlatform;
import java.util.Map; import java.util.Map;
import io.flutter.app.FlutterApplication; import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MyApplication extends FlutterApplication { public class MyApplication extends FlutterApplication {
@Override @Override
...@@ -25,17 +24,9 @@ public class MyApplication extends FlutterApplication { ...@@ -25,17 +24,9 @@ public class MyApplication extends FlutterApplication {
return MyApplication.this; return MyApplication.this;
} }
/**
* 获取应用入口的Activity,这个Activity在应用交互期间应该是一直在栈底的
* @return
*/
@Override @Override
public Activity getMainActivity() { public void onRegisterPlugins(PluginRegistry registry) {
if (MainActivity.sRef != null) { GeneratedPluginRegistrant.registerWith(registry);
return MainActivity.sRef.get();
}
return null;
} }
@Override @Override
......
Future<Map<String,dynamic>> open(String url,{Map<String,dynamic> urlParams,Map<String,dynamic> exts}){
}
void close(String id,{Map<String,dynamic> result,Map<String,dynamic> exts}){
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment