Commit 28e3e2e7 authored by yangwu.jia's avatar yangwu.jia

Merge branch 'feature/flutter_1.9_upgrade' into feature/flutter_1.9_androidx_upgrade

parents 2f595499 a8ba6798
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.idlefish.flutterboost">
<application>
<activity android:name="com.idlefish.flutterboost.containers.BoostFlutterDefaultActivity" />
</application>
</manifest>
......@@ -84,6 +84,13 @@ public class FlutterViewContainerManager implements IContainerManager {
void removeRecord(IContainerRecord record) {
mRecordStack.remove(record);
mRecordMap.remove(record.getContainer());
if(mRecordStack.empty()){
if( NewFlutterBoost.instance().platform().whenEngineDestroy()== NewFlutterBoost.ConfigBuilder.All_FLUTTER_ACTIVITY_DESTROY){
NewFlutterBoost.instance().boostDestroy();
}
}
}
void setContainerResult(IContainerRecord record,int requestCode, int resultCode, Map<String,Object> result) {
......
......@@ -10,7 +10,10 @@ import com.idlefish.flutterboost.interfaces.*;
import io.flutter.Log;
import io.flutter.embedding.android.FlutterView;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterShellArgs;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.embedding.engine.plugins.shim.ShimPluginRegistry;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.view.FlutterMain;
import java.util.HashMap;
......@@ -21,9 +24,9 @@ public class NewFlutterBoost {
private Platform mPlatform;
private FlutterViewContainerManager mManager;
private FlutterEngine mEngine;
private Activity mCurrentActiveActivity;
private BoostPluginRegistry mRegistry;
private PluginRegistry mRegistry;
static NewFlutterBoost sInstance = null;
......@@ -41,19 +44,18 @@ public class NewFlutterBoost {
mManager = new FlutterViewContainerManager();
mRegistry = new BoostPluginRegistry(this.engineProvider(),
mPlatform.getApplication());
platform.getApplication().registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
Log.e("bbbb1", "xxxxx");
mCurrentActiveActivity=activity;
if (mPlatform.whenEngineStart() == ConfigBuilder.ANY_ACTIVITY_CREATED) {
Log.e("bbbb2", "xxxxx");
mRegistry.currentActivity(activity);
doInitialFlutterViewRun(mPlatform,mRegistry);
doInitialFlutter();
}
}
......@@ -62,7 +64,7 @@ public class NewFlutterBoost {
if (mCurrentActiveActivity == null) {
Debuger.log("Application entry foreground");
if (NewFlutterBoost.instance().engineProvider() != null) {
if (createEngine() != null) {
HashMap<String, String> map = new HashMap<>();
map.put("type", "foreground");
channel().sendEvent("lifecycle", map);
......@@ -86,7 +88,7 @@ public class NewFlutterBoost {
if (mCurrentActiveActivity == activity) {
Debuger.log("Application entry background");
if (mPlatform.engineProvider() != null) {
if (createEngine() != null) {
HashMap<String, String> map = new HashMap<>();
map.put("type", "background");
channel().sendEvent("lifecycle", map);
......@@ -105,7 +107,7 @@ public class NewFlutterBoost {
if (mCurrentActiveActivity == activity) {
Debuger.log("Application entry background");
if (mPlatform.engineProvider() != null) {
if (createEngine() != null) {
HashMap<String, String> map = new HashMap<>();
map.put("type", "background");
channel().sendEvent("lifecycle", map);
......@@ -117,32 +119,35 @@ public class NewFlutterBoost {
if (mPlatform.whenEngineStart() == ConfigBuilder.IMMEDIATELY) {
doInitialFlutterViewRun(mPlatform,mRegistry);
doInitialFlutter();
}
}
private void doInitialFlutterViewRun(Platform platform,BoostPluginRegistry registry) {
// Don't attempt to start a FlutterEngine if we're using a cached FlutterEngine.
// if (host.getCachedEngineId() != null) {
// return;
// }
FlutterEngine flutterEngine = platform.engineProvider();
public void doInitialFlutter() {
if(mEngine!=null) return;
FlutterEngine flutterEngine = createEngine();
if(mPlatform.lifecycleListener!=null){
mPlatform.lifecycleListener.onEngineCreated();
}
if (flutterEngine.getDartExecutor().isExecutingDart()) {
// No warning is logged because this situation will happen on every config
// change if the developer does not choose to retain the Fragment instance.
// So this is expected behavior in many cases.
return;
}
platform.registerPlugins(registry);
// The engine needs to receive the Flutter app's initial route before executing any
// Dart code to ensure that the initial route arrives in time to be applied.
if (platform.initialRoute() != null) {
flutterEngine.getNavigationChannel().setInitialRoute(platform.initialRoute());
if (mPlatform.initialRoute() != null) {
flutterEngine.getNavigationChannel().setInitialRoute(mPlatform.initialRoute());
}
// Configure the Dart entrypoint and execute it.
DartExecutor.DartEntrypoint entrypoint = new DartExecutor.DartEntrypoint(
......@@ -150,6 +155,18 @@ public class NewFlutterBoost {
"main"
);
flutterEngine.getDartExecutor().executeDartEntrypoint(entrypoint);
mRegistry = new BoostPluginRegistry(createEngine(),mPlatform.getApplication());
((BoostPluginRegistry) mRegistry).currentActivity(mCurrentActiveActivity);
mPlatform.registerPlugins(mRegistry);
if(mPlatform.lifecycleListener!=null){
mPlatform.lifecycleListener.onPluginsRegistered();
}
}
......@@ -161,10 +178,16 @@ public class NewFlutterBoost {
public static int ANY_ACTIVITY_CREATED = 1; //当有任何Activity创建时,启动引擎
public static int FLUTTER_ACTIVITY_CREATED = 2; //当有flutterActivity创建时,启动引擎
public static int APP_EXit = 0; //所有flutter Activity destory 时,销毁engine
public static int All_FLUTTER_ACTIVITY_DESTROY = 1; //所有flutter Activity destory 时,销毁engine
private String dartEntrypoint = DEFAULT_DART_ENTRYPOINT;
private String initialRoute = DEFAULT_INITIAL_ROUTE;
private int whenEngineStart = ANY_ACTIVITY_CREATED;
private int whenEngineDestory = APP_EXit;
private boolean isDebug = false;
......@@ -175,6 +198,8 @@ public class NewFlutterBoost {
private INativeRouter router = null;
private BoostLifecycleListener lifecycleListener;
public ConfigBuilder(Application app, INativeRouter router) {
this.router = router;
this.mApp = app;
......@@ -200,11 +225,19 @@ public class NewFlutterBoost {
return this;
}
public ConfigBuilder whenEngineStart(@NonNull int whenEngineStart) {
public ConfigBuilder whenEngineStart( int whenEngineStart) {
this.whenEngineStart = whenEngineStart;
return this;
}
public ConfigBuilder whenEngineDestory( int whenEngineDestory) {
this.whenEngineDestory = whenEngineDestory;
return this;
}
public ConfigBuilder lifecycleListener( BoostLifecycleListener lifecycleListener) {
this.lifecycleListener = lifecycleListener;
return this;
}
public Platform build() {
Platform platform = new Platform() {
......@@ -232,22 +265,24 @@ public class NewFlutterBoost {
return ConfigBuilder.this.whenEngineStart;
}
@Override
public int whenEngineDestroy() {
return ConfigBuilder.this.whenEngineDestory;
}
public FlutterView.RenderMode renderMode() {
return ConfigBuilder.this.renderMode;
}
};
platform.lifecycleListener=this.lifecycleListener;
return platform;
}
}
public FlutterEngine engineProvider() {
return sInstance.mPlatform.engineProvider();
}
public IContainerManager containerManager() {
return sInstance.mManager;
}
......@@ -268,7 +303,47 @@ public class NewFlutterBoost {
return mManager.findContainerById(id);
}
public BoostPluginRegistry getPluginRegistry(){
public PluginRegistry getPluginRegistry(){
return mRegistry;
}
private FlutterEngine createEngine(){
if (mEngine == null) {
FlutterMain.startInitialization(mPlatform.getApplication());
FlutterShellArgs flutterShellArgs = new FlutterShellArgs(new String[0]);
FlutterMain.ensureInitializationComplete(
mPlatform.getApplication().getApplicationContext(), flutterShellArgs.toArray());
mEngine = new FlutterEngine(mPlatform.getApplication().getApplicationContext());
}
return mEngine;
}
public FlutterEngine engineProvider() {
return mEngine;
}
public void boostDestroy(){
if(mEngine!=null){
mEngine.destroy();
}
if(mPlatform.lifecycleListener!=null){
mPlatform.lifecycleListener.onEngineDestroy();
}
mEngine=null;
mRegistry=null;
mCurrentActiveActivity=null;
}
public interface BoostLifecycleListener {
void onEngineCreated();
void onPluginsRegistered();
void onEngineDestroy();
}
}
......@@ -8,54 +8,38 @@ import java.lang.reflect.Method;
import java.util.Map;
import io.flutter.embedding.android.FlutterView;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterShellArgs;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.view.FlutterMain;
public abstract class Platform {
public abstract Application getApplication();
public FlutterEngine mEngine ;
public abstract void openContainer(Context context, String url, Map<String, Object> urlParams, int requestCode, Map<String, Object> exts);
public abstract Application getApplication();
public abstract int whenEngineStart();
public abstract int whenEngineDestroy();
public abstract void openContainer(Context context, String url, Map<String,Object> urlParams, int requestCode, Map<String,Object> exts);
public abstract FlutterView.RenderMode renderMode();
public abstract int whenEngineStart() ;
public abstract boolean isDebug();
public abstract FlutterView.RenderMode renderMode();
public abstract boolean isDebug() ;
public abstract String initialRoute();
public abstract String initialRoute();
public NewFlutterBoost.BoostLifecycleListener lifecycleListener;
public void closeContainer(IContainerRecord record, Map<String, Object> result, Map<String, Object> exts) {
if(record == null) return;
if (record == null) return;
record.getContainer().finishContainer(result);
}
public FlutterEngine engineProvider() {
if (mEngine == null) {
FlutterShellArgs flutterShellArgs = new FlutterShellArgs(new String[0]);
FlutterMain.ensureInitializationComplete(
getApplication().getApplicationContext(), flutterShellArgs.toArray());
mEngine = new FlutterEngine( getApplication().getApplicationContext());
}
return mEngine;
}
public void registerPlugins(PluginRegistry registry) {
public void registerPlugins(PluginRegistry registry) {
try {
Class clz = Class.forName("io.flutter.plugins.GeneratedPluginRegistrant");
Method method = clz.getDeclaredMethod("registerWith",PluginRegistry.class);
method.invoke(null,registry);
}catch (Throwable t){
Method method = clz.getDeclaredMethod("registerWith", PluginRegistry.class);
method.invoke(null, registry);
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
......
......@@ -263,7 +263,7 @@ public class Utils {
return;
}
String [] arr = new String[]{"mServedView", "mNextServedView"};
String [] arr = new String[]{"mLastSrvView","mServedView", "mNextServedView"};
Field f = null;
Object obj_get = null;
for (int i = 0;i < arr.length;i ++) {
......@@ -283,7 +283,7 @@ public class Utils {
}
}
}catch(Throwable t){
t.printStackTrace();
// t.printStackTrace();
}
}
}
......
......@@ -77,8 +77,9 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
void onAttach(@NonNull Context context) {
ensureAlive();
initializeFlutter(context);
if (NewFlutterBoost.instance().platform().whenEngineStart() == NewFlutterBoost.ConfigBuilder.FLUTTER_ACTIVITY_CREATED) {
NewFlutterBoost.instance().doInitialFlutter();
}
// When "retain instance" is true, the FlutterEngine will survive configuration
// changes. Therefore, we create a new one only if one does not already exist.
......@@ -109,32 +110,18 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
host.getActivity(),
host.getLifecycle()
);
}
host.configureFlutterEngine(flutterEngine);
}
private void initializeFlutter(@NonNull Context context) {
FlutterMain.ensureInitializationComplete(
context.getApplicationContext(),
host.getFlutterShellArgs().toArray()
);
}
private void setupFlutterEngine() {
Log.d(TAG, "Setting up FlutterEngine.");
// First, check if the host wants to use a cached FlutterEngine.
// String cachedEngineId = host.getCachedEngineId();
// if (cachedEngineId != null) {
// flutterEngine = FlutterEngineCache.getInstance().get(cachedEngineId);
// isFlutterEngineFromHost = true;
// if (flutterEngine == null) {
// throw new IllegalStateException("The requested cached FlutterEngine did not exist in the FlutterEngineCache: '" + cachedEngineId + "'");
// }
// return;
// }
// Second, defer to subclasses for a custom FlutterEngine.
flutterEngine = host.provideFlutterEngine(host.getContext());
......@@ -147,7 +134,6 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
// FlutterView.
Log.d(TAG, "No preferred FlutterEngine was provided. Creating a new FlutterEngine for"
+ " this NewFlutterFragment.");
flutterEngine = new FlutterEngine(host.getContext());
isFlutterEngineFromHost = false;
}
......@@ -263,16 +249,6 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
Utils.fixInputMethodManagerLeak(host.getActivity());
// Destroy our FlutterEngine if we're not set to retain it.
// if (host.shouldDestroyEngineWithHost()) {
// flutterEngine.destroy();
//
// if (host.getCachedEngineId() != null) {
// FlutterEngineCache.getInstance().remove(host.getCachedEngineId());
// }
//
// flutterEngine = null;
// }
}
......@@ -280,12 +256,6 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
mSyncer.onBackPressed();
ensureAlive();
// if (flutterEngine != null) {
// Log.v(TAG, "Forwarding onBackPressed() to FlutterEngine.");
// flutterEngine.getNavigationChannel().popRoute();
// } else {
// Log.w(TAG, "Invoked onBackPressed() before NewFlutterFragment was attached to an Activity.");
// }
}
......
......@@ -485,7 +485,7 @@ public class NewFlutterFragment extends Fragment implements FlutterActivityAndFr
*/
@Override
public boolean shouldAttachEngineToActivity() {
return getArguments().getBoolean(ARG_SHOULD_ATTACH_ENGINE_TO_ACTIVITY);
return true;
}
......
......@@ -3,19 +3,20 @@ package com.taobao.idlefish.flutterboostexample;
import android.app.Application;
import android.content.Context;
import android.util.Log;
import com.idlefish.flutterboost.*;
import com.idlefish.flutterboost.interfaces.IContainerRecord;
import java.util.Map;
import com.idlefish.flutterboost.interfaces.INativeRouter;
import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.MethodChannel;
public class MyApplication extends Application {
public class MyApplication extends FlutterApplication {
@Override
public void onCreate() {
super.onCreate();
INativeRouter router =new INativeRouter() {
@Override
public void openContainer(Context context, String url, Map<String, Object> urlParams, int requestCode, Map<String, Object> exts) {
......@@ -25,12 +26,35 @@ public class MyApplication extends FlutterApplication {
};
NewFlutterBoost.BoostLifecycleListener lifecycleListener= new NewFlutterBoost.BoostLifecycleListener() {
@Override
public void onEngineCreated() {
}
@Override
public void onPluginsRegistered() {
MethodChannel mMethodChannel = new MethodChannel( NewFlutterBoost.instance().engineProvider().getDartExecutor(), "methodChannel");
Log.e("MyApplication","MethodChannel create");
TextPlatformViewPlugin.register(NewFlutterBoost.instance().getPluginRegistry().registrarFor("TextPlatformViewPlugin"));
}
@Override
public void onEngineDestroy() {
}
};
Platform platform= new NewFlutterBoost
.ConfigBuilder(this,router)
.isDebug(true)
.whenEngineStart(NewFlutterBoost.ConfigBuilder.ANY_ACTIVITY_CREATED)
.lifecycleListener(lifecycleListener)
.build();
NewFlutterBoost.instance().init(platform);
}
}
package com.taobao.idlefish.flutterboostexample;
import io.flutter.app.FlutterPluginRegistry;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.StandardMessageCodec;
public class TextPlatformViewPlugin {
public static void register(FlutterPluginRegistry registry) {
registry.getPlatformViewsController().getRegistry().registerViewFactory("plugins.test/view",
public static void register(PluginRegistry.Registrar registrar) {
registrar.platformViewRegistry().registerViewFactory("plugins.test/view",
new TextPlatformViewFactory(StandardMessageCodec.INSTANCE));
}
}
......@@ -20,6 +20,7 @@ class _MyAppState extends State<MyApp> {
'first': (pageName, params, _) => FirstRouteWidget(),
'second': (pageName, params, _) => SecondRouteWidget(),
'tab': (pageName, params, _) => TabRouteWidget(),
'platformView': (pageName, params, _) => PlatformRouteWidget(),
'flutterFragment': (pageName, params, _) => FragmentRouteWidget(params),
///可以在native层通过 getContainerParams 来传递参数
'flutterPage': (pageName, params, _) {
......
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
typedef void TextViewCreatedCallback(TextViewController controller);
class TextView extends StatefulWidget {
const TextView({
Key key,
this.onTextViewCreated,
}) : super(key: key);
final TextViewCreatedCallback onTextViewCreated;
@override
State<StatefulWidget> createState() => _TextViewState();
}
class _TextViewState extends State<TextView> {
@override
Widget build(BuildContext context) {
if (defaultTargetPlatform == TargetPlatform.android) {
return AndroidView(
viewType: 'plugins.test/view',
onPlatformViewCreated: _onPlatformViewCreated,
);
}
return Text(
'$defaultTargetPlatform is not yet supported by the text_view plugin');
}
void _onPlatformViewCreated(int id) {
if (widget.onTextViewCreated == null) {
return;
}
widget.onTextViewCreated(new TextViewController._(id));
}
}
class TextViewController {
TextViewController._(int id)
: _channel = new MethodChannel('plugins.felix.angelov/textview_$id');
final MethodChannel _channel;
Future<void> setText(String text) async {
assert(text != null);
return _channel.invokeMethod('setText', text);
}
}
\ No newline at end of file
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_boost/flutter_boost.dart';
import 'package:flutter_boost_example/platform_view.dart';
class FirstRouteWidget extends StatelessWidget {
@override
......@@ -68,6 +69,28 @@ class TabRouteWidget extends StatelessWidget {
}
}
class PlatformRouteWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title:Text("Platform Route"),
),
body: Center(
child: RaisedButton(
child: TextView(),
onPressed: () {
print("open second page!");
FlutterBoost.singleton.open("second").then((Map value) {
print(
"call me when page is finished. did recieve second route result $value");
});
},
),
),
);
}
}
class FlutterRouteWidget extends StatefulWidget {
FlutterRouteWidget({this.params,this.message});
final Map params;
......@@ -216,6 +239,21 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
MaterialPageRoute(builder: (_) => PushWidget()));
},
),
InkWell(
child: Container(
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
color: Colors.yellow,
child: Text(
'push Platform demo',
style: TextStyle(fontSize: 22.0, color: Colors.black),
)),
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (_) => PlatformRouteWidget()));
},
),
InkWell(
child: Container(
padding: const EdgeInsets.all(8.0),
......
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