Commit 9537ef83 authored by yangwu.jia's avatar yangwu.jia

Merge branch 'feature/base_flutter_1.12_upgrade' into...

Merge branch 'feature/base_flutter_1.12_upgrade' into feature/base_flutter_1.12_upgrade_for_androidx

# Conflicts:
#	android/src/main/java/com/idlefish/flutterboost/Platform.java
#	android/src/main/java/com/idlefish/flutterboost/XFlutterTextureView.java
#	android/src/main/java/com/idlefish/flutterboost/containers/FlutterSplashView.java
#	example/android/gradle.properties
parents 12f38de5 1357271b
# Configuration for probot-no-response - https://github.com/probot/no-response
# Number of days of inactivity before an Issue is closed for lack of response
daysUntilClose: 21
# Label requiring a response
responseRequiredLabel: more-information-needed
# Comment to post when closing an Issue for lack of response. Set to `false` to disable
closeComment: >
This issue has been automatically closed because there has been no response
to our request for more information from the original author. With only the
information that is currently in the issue, we don't have enough information
to take action. Please reach out if you have or find the answers we need so
that we can investigate further.
Thanks for your contribution.
...@@ -38,6 +38,14 @@ ios: ...@@ -38,6 +38,14 @@ ios:
iOS: iOS:
no change no change
## 0.1.63
android:
Fixed bugs
iOS:
no change
### API changes ### API changes
From the point of API changes, we did some refactoring as following: From the point of API changes, we did some refactoring as following:
#### iOS API changes #### iOS API changes
......
### 在FlutterBoost下如何管理Flutter页面的生命周期?原生的Flutter的AppLifecycleState事件会不一致,比如ViewAppear会导致app状态suspending或者paused。混合栈怎么处理?
回答:在混合栈下,页面事件基于以下自定义的事件:
```dart
enum ContainerLifeCycle {
Init,
Appear,
WillDisappear,
Disappear,
Destroy,
Background,
Foreground
}
```
对于页面事件重复,请参考下面的FAQ。
### 如何判断flutter的widget或者container是当前可见的?
回答:有个api可以判断当前页面是否可见:
```dart
bool isTopContainer = FlutterBoost.BoostContainer.of(context).onstage
```
传入你widget的context,就能判断你的widget是否是可见的
基于这个API,可以判断你的widget是否可见,从而避免接收一些重复的生命周期消息。参考这个issue:https://github.com/alibaba/flutter_boost/issues/498
### 您好,我想请教一下flutter_boost有关的问题:ABC三个都是flutter页面,从 A页面 -> B页面 -> C页面,当打开C页面时希望自动关掉B页面,当从C页面返回时直接返回A页面,可有什么方法?
回答:你只需要操作Native层的UINavigationController里的vc数组就可以了。就如同平时你操作普通的UIViewController一样。因为FlutterBoost对Native层的FlutterViewController和Dart层的flutter page的生命周期管理是一致的,当FlutterViewController被销毁,其在dart层管理的flutter page也会自动被销毁。
### 在ios中voice over打开,demo在点击交互会crash
回答:无障碍模式下目前Flutter Engine有bug,已经提交issue和PR给flutter啦。请参考这个issue:https://github.com/alibaba/flutter_boost/issues/488及其分析。提交给flutter的PR见这里:https://github.com/flutter/engine/pull/14155
### 似乎官方已经提供了混合栈的功能,参考这里:https://flutter.dev/docs/development/add-to-app; FlutterBoost是否有存在的必要?
回答:官方的解决方案仅仅是在native侧对FlutterViewController和Flutterengine进行解耦,如此可以一个FlutterEngine切换不同的FlutterViewController或者Activity进行渲染。但其并未解决Native和Flutter页面混合的问题,无法保证两侧的页面生命周期一致。即使是Flutter官方针对这个问题也是建议使用FlutterBoost。
其差别主要有:
|*|FlutterBoost1.5 |Flutter官方方案 |其他框架|
|----|----|----|----|
|是否支持混合页面之间随意跳转 |Y |N |Y|
|一致的页面生命周期管理(多Flutter页面) |Y |N |?|
|是否支持页面间数据传递(回传等) |Y |N |N|
|是否支持测滑手势 |Y |Y |Y|
|是否支持跨页的hero动画 |N |Y |N|
|内存等资源占用是否可控 |Y |Y |Y|
|是否提供一致的页面route方案 |Y |Y |N|
|iOS和Android能力及接口是否一致 |Y |N |N|
|框架是否稳定,支持Flutter1.9 |Y |N |?|
|是否已经支持到View级别混合 |N |N |N|
同时FlutterBoost也提供了一次性创建混合工程的命令:flutterboot。代码参考:https://github.com/alibaba-flutter/flutter-boot
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
# Release Note # Release Note
Please checkout the release note for the latest 0.1.61 to see changes [0.1.61 release note](https://github.com/alibaba/flutter_boost/releases) Please checkout the release note for the latest 0.1.63 to see changes [0.1.63 release note](https://github.com/alibaba/flutter_boost/releases)
# FlutterBoost # FlutterBoost
A next-generation Flutter-Native hybrid solution. FlutterBoost is a Flutter plugin which enables hybrid integration of Flutter for your existing native apps with minimum efforts.The philosophy of FlutterBoost is to use Flutter as easy as using a WebView. Managing Native pages and Flutter pages at the same time is non-trivial in an existing App. FlutterBoost takes care of page resolution for you. The only thing you need to care about is the name of the page(usually could be an URL).  A next-generation Flutter-Native hybrid solution. FlutterBoost is a Flutter plugin which enables hybrid integration of Flutter for your existing native apps with minimum efforts.The philosophy of FlutterBoost is to use Flutter as easy as using a WebView. Managing Native pages and Flutter pages at the same time is non-trivial in an existing App. FlutterBoost takes care of page resolution for you. The only thing you need to care about is the name of the page(usually could be an URL). 
...@@ -27,16 +27,16 @@ You need to add Flutter to your project before moving on.The version of the flut ...@@ -27,16 +27,16 @@ You need to add Flutter to your project before moving on.The version of the flut
3. 0.1.60 is based on the flutter v1.9.1-hotfixes branch. Android does not support andriodx if other flutter branches will compile incorrectly 3. 0.1.60 is based on the flutter v1.9.1-hotfixes branch. Android does not support andriodx if other flutter branches will compile incorrectly
4. 0.1.61 is a bugfix for 0.1.60 4. 0.1.61--0.1.62 is a bugfix for 0.1.60
5. Statement of support for androidx 5. Statement of support for androidx
Current androidx branch is feature/flutter_1.9_androidx_upgrade Current androidx branch is v0.1.61-androidx-hotfixes
Is based on flutter v1.9.1-hotfixes branch, if other branches will compile incorrectly Is based on flutter v1.9.1-hotfixes branch, if other branches will compile incorrectly
Synchronize with the 0.1.60 code, and bugfix of 0.1.61 also merge to this branch. Synchronize with the 0.1.63 code, and bugfix also merge to this branch.
...@@ -52,14 +52,14 @@ support branch ...@@ -52,14 +52,14 @@ support branch
flutter_boost: flutter_boost:
git: git:
url: 'https://github.com/alibaba/flutter_boost.git' url: 'https://github.com/alibaba/flutter_boost.git'
ref: '0.1.61' ref: '0.1.63'
``` ```
androidx branch androidx branch
```json ```json
flutter_boost: flutter_boost:
git: git:
url: 'https://github.com/alibaba/flutter_boost.git' url: 'https://github.com/alibaba/flutter_boost.git'
ref: 'feature/flutter_1.9_androidx_upgrade' ref: 'v0.1.61-androidx-hotfixes'
``` ```
...@@ -68,7 +68,9 @@ flutter_boost: ...@@ -68,7 +68,9 @@ flutter_boost:
Please see the boost example for details. Please see the boost example for details.
# FAQ
please read this document:
<a href="Frequently Asked Question.md">FAQ</a>
# License # License
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
# Release Note # Release Note
请查看最新版本0.1.61的release note 确认变更,[0.1.61 release note](https://github.com/alibaba/flutter_boost/releases) 请查看最新版本0.1.63的release note 确认变更,[0.1.63 release note](https://github.com/alibaba/flutter_boost/releases)
# FlutterBoost # FlutterBoost
...@@ -16,6 +16,10 @@ ...@@ -16,6 +16,10 @@
在继续之前,您需要将Flutter集成到你现有的项目中。flutter sdk 的版本需要 v1.9.1-hotfixes,否则会编译失败. 在继续之前,您需要将Flutter集成到你现有的项目中。flutter sdk 的版本需要 v1.9.1-hotfixes,否则会编译失败.
# FAQ
请阅读这篇文章:
<a href="Frequently Asked Question.md">FAQ</a>
# boost 版本说明 # boost 版本说明
...@@ -26,16 +30,16 @@ ...@@ -26,16 +30,16 @@
3. 0.1.60 是基于flutter v1.9.1-hotfixes 分支,android如果其他flutter分支会编译错误,该版本不支持andriodx 3. 0.1.60 是基于flutter v1.9.1-hotfixes 分支,android如果其他flutter分支会编译错误,该版本不支持andriodx
4. 0.1.61 是对0.1.60 的bugfix 4. 0.1.61-- 0.1.63 是对0.1.60 的bugfix
5. 关于androidx 的支持声明 5. 关于androidx 的支持声明
目前androidx 分支为 feature/flutter_1.9_androidx_upgrade 目前androidx 分支为 v0.1.61-androidx-hotfixes
是基于flutter v1.9.1-hotfixes 分支,如果其他分支会编译错误 是基于flutter v1.9.1-hotfixes 分支,如果其他分支会编译错误
和0.1.60代码同步,同时0.1.61的 bugfix 也会合入该分支。 和0.1.60代码同步, bugfix 也会合入该分支。
...@@ -52,7 +56,7 @@ support分支 ...@@ -52,7 +56,7 @@ support分支
flutter_boost: flutter_boost:
git: git:
url: 'https://github.com/alibaba/flutter_boost.git' url: 'https://github.com/alibaba/flutter_boost.git'
ref: '0.1.61' ref: '0.1.63'
``` ```
...@@ -61,7 +65,7 @@ androidx分支 ...@@ -61,7 +65,7 @@ androidx分支
flutter_boost: flutter_boost:
git: git:
url: 'https://github.com/alibaba/flutter_boost.git' url: 'https://github.com/alibaba/flutter_boost.git'
ref: 'feature/flutter_1.9_androidx_upgrade' ref: 'v0.1.61-androidx-hotfixes'
``` ```
......
...@@ -29,6 +29,7 @@ public class FlutterBoost { ...@@ -29,6 +29,7 @@ public class FlutterBoost {
static FlutterBoost sInstance = null; static FlutterBoost sInstance = null;
private long FlutterPostFrameCallTime = 0; private long FlutterPostFrameCallTime = 0;
private Application.ActivityLifecycleCallbacks mActivityLifecycleCallbacks;
public long getFlutterPostFrameCallTime() { public long getFlutterPostFrameCallTime() {
return FlutterPostFrameCallTime; return FlutterPostFrameCallTime;
...@@ -51,7 +52,7 @@ public class FlutterBoost { ...@@ -51,7 +52,7 @@ public class FlutterBoost {
mPlatform = platform; mPlatform = platform;
mManager = new FlutterViewContainerManager(); mManager = new FlutterViewContainerManager();
platform.getApplication().registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() { mActivityLifecycleCallbacks = new Application.ActivityLifecycleCallbacks() {
@Override @Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) { public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
...@@ -123,7 +124,9 @@ public class FlutterBoost { ...@@ -123,7 +124,9 @@ public class FlutterBoost {
mCurrentActiveActivity = null; mCurrentActiveActivity = null;
} }
} }
}); };
platform.getApplication().registerActivityLifecycleCallbacks(mActivityLifecycleCallbacks);
if (mPlatform.whenEngineStart() == ConfigBuilder.IMMEDIATELY) { if (mPlatform.whenEngineStart() == ConfigBuilder.IMMEDIATELY) {
...@@ -231,10 +234,7 @@ public class FlutterBoost { ...@@ -231,10 +234,7 @@ public class FlutterBoost {
return this; return this;
} }
public ConfigBuilder whenEngineDestory(int whenEngineDestory) {
this.whenEngineDestory = whenEngineDestory;
return this;
}
public ConfigBuilder lifecycleListener(BoostLifecycleListener lifecycleListener) { public ConfigBuilder lifecycleListener(BoostLifecycleListener lifecycleListener) {
this.lifecycleListener = lifecycleListener; this.lifecycleListener = lifecycleListener;
...@@ -271,10 +271,6 @@ public class FlutterBoost { ...@@ -271,10 +271,6 @@ public class FlutterBoost {
return ConfigBuilder.this.whenEngineStart; return ConfigBuilder.this.whenEngineStart;
} }
@Override
public int whenEngineDestroy() {
return ConfigBuilder.this.whenEngineDestory;
}
public FlutterView.RenderMode renderMode() { public FlutterView.RenderMode renderMode() {
return ConfigBuilder.this.renderMode; return ConfigBuilder.this.renderMode;
......
...@@ -82,11 +82,9 @@ public class FlutterViewContainerManager implements IContainerManager { ...@@ -82,11 +82,9 @@ public class FlutterViewContainerManager implements IContainerManager {
void removeRecord(IContainerRecord record) { void removeRecord(IContainerRecord record) {
mRecordStack.remove(record); mRecordStack.remove(record);
mRecordMap.remove(record.getContainer()); mRecordMap.remove(record.getContainer());
if(mRecordMap.isEmpty()){ // if(mRecordMap.isEmpty()){
if( FlutterBoost.instance().platform().whenEngineDestroy()== FlutterBoost.ConfigBuilder.All_FLUTTER_ACTIVITY_DESTROY){ //
FlutterBoost.instance().boostDestroy(); // }
}
}
} }
......
...@@ -19,7 +19,6 @@ public abstract class Platform { ...@@ -19,7 +19,6 @@ public abstract class Platform {
public abstract int whenEngineStart(); public abstract int whenEngineStart();
public abstract int whenEngineDestroy();
public abstract FlutterView.RenderMode renderMode(); public abstract FlutterView.RenderMode renderMode();
......
package com.idlefish.flutterboost;
import android.content.Context;
import android.graphics.SurfaceTexture;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.util.AttributeSet;
import android.view.Surface;
import android.view.TextureView;
import io.flutter.Log;
import io.flutter.embedding.engine.renderer.FlutterRenderer;
import io.flutter.embedding.engine.renderer.OnFirstFrameRenderedListener;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class XFlutterTextureView extends TextureView implements FlutterRenderer.RenderSurface {
private static final String TAG = "XFlutterTextureView";
private boolean isSurfaceAvailableForRendering;
private boolean isAttachedToFlutterRenderer;
@Nullable
private FlutterRenderer flutterRenderer;
@NonNull
private Set<OnFirstFrameRenderedListener> onFirstFrameRenderedListeners;
private final SurfaceTextureListener surfaceTextureListener;
public XFlutterTextureView(@NonNull Context context) {
this(context, (AttributeSet)null);
}
public XFlutterTextureView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
this.isSurfaceAvailableForRendering = false;
this.isAttachedToFlutterRenderer = false;
this.onFirstFrameRenderedListeners = new HashSet();
this.surfaceTextureListener = new SurfaceTextureListener() {
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
Log.v("FlutterTextureView", "SurfaceTextureListener.onSurfaceTextureAvailable()");
XFlutterTextureView.this.isSurfaceAvailableForRendering = true;
if (XFlutterTextureView.this.isAttachedToFlutterRenderer) {
XFlutterTextureView.this.connectSurfaceToRenderer();
}
}
public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {
Log.v("FlutterTextureView", "SurfaceTextureListener.onSurfaceTextureSizeChanged()");
if (XFlutterTextureView.this.isAttachedToFlutterRenderer) {
XFlutterTextureView.this.changeSurfaceSize(width, height);
}
}
public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {
}
public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
Log.v("FlutterTextureView", "SurfaceTextureListener.onSurfaceTextureDestroyed()");
XFlutterTextureView.this.isSurfaceAvailableForRendering = false;
if (XFlutterTextureView.this.isAttachedToFlutterRenderer) {
XFlutterTextureView.this.disconnectSurfaceFromRenderer();
}
return true;
}
};
this.init();
}
private void init() {
this.setSurfaceTextureListener(this.surfaceTextureListener);
}
public void attachToRenderer(@NonNull FlutterRenderer flutterRenderer) {
Log.v("FlutterTextureView", "Attaching to FlutterRenderer.");
if (this.flutterRenderer != null) {
Log.v("FlutterTextureView", "Already connected to a FlutterRenderer. Detaching from old one and attaching to new one.");
this.flutterRenderer.detachFromRenderSurface();
}
this.flutterRenderer = flutterRenderer;
this.isAttachedToFlutterRenderer = true;
if (this.isSurfaceAvailableForRendering) {
Log.v("FlutterTextureView", "Surface is available for rendering. Connecting FlutterRenderer to Android surface.");
this.connectSurfaceToRenderer();
}
}
public void detachFromRenderer() {
if (this.flutterRenderer != null) {
if (this.getWindowToken() != null) {
Log.v("FlutterTextureView", "Disconnecting FlutterRenderer from Android surface.");
this.disconnectSurfaceFromRenderer();
}
this.flutterRenderer = null;
this.isAttachedToFlutterRenderer = false;
} else {
Log.w("FlutterTextureView", "detachFromRenderer() invoked when no FlutterRenderer was attached.");
}
}
private void connectSurfaceToRenderer() {
if (this.flutterRenderer != null && this.getSurfaceTexture() != null) {
Surface surface= new Surface(this.getSurfaceTexture());
this.flutterRenderer.surfaceCreated(surface);
surface.release();
} else {
throw new IllegalStateException("connectSurfaceToRenderer() should only be called when flutterRenderer and getSurfaceTexture() are non-null.");
}
}
private void changeSurfaceSize(int width, int height) {
if (this.flutterRenderer == null) {
throw new IllegalStateException("changeSurfaceSize() should only be called when flutterRenderer is non-null.");
} else {
Log.v("FlutterTextureView", "Notifying FlutterRenderer that Android surface size has changed to " + width + " x " + height);
this.flutterRenderer.surfaceChanged(width, height);
}
}
private void disconnectSurfaceFromRenderer() {
if (this.flutterRenderer == null) {
throw new IllegalStateException("disconnectSurfaceFromRenderer() should only be called when flutterRenderer is non-null.");
} else {
this.flutterRenderer.surfaceDestroyed();
}
}
public void addOnFirstFrameRenderedListener(@NonNull OnFirstFrameRenderedListener listener) {
this.onFirstFrameRenderedListeners.add(listener);
}
public void removeOnFirstFrameRenderedListener(@NonNull OnFirstFrameRenderedListener listener) {
this.onFirstFrameRenderedListeners.remove(listener);
}
public void onFirstFrameRendered() {
Log.v("FlutterTextureView", "onFirstFrameRendered()");
Iterator var1 = this.onFirstFrameRenderedListeners.iterator();
while(var1.hasNext()) {
OnFirstFrameRenderedListener listener = (OnFirstFrameRenderedListener)var1.next();
listener.onFirstFrameRendered();
}
}
}
\ No newline at end of file
...@@ -36,7 +36,8 @@ import io.flutter.Log; ...@@ -36,7 +36,8 @@ import io.flutter.Log;
import io.flutter.embedding.android.*; import io.flutter.embedding.android.*;
import io.flutter.embedding.engine.FlutterEngine; import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.renderer.FlutterRenderer; import io.flutter.embedding.engine.renderer.FlutterRenderer;
import io.flutter.embedding.engine.renderer.OnFirstFrameRenderedListener; import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener;
import io.flutter.embedding.engine.renderer.RenderSurface;
import io.flutter.embedding.engine.systemchannels.TextInputChannel; import io.flutter.embedding.engine.systemchannels.TextInputChannel;
import io.flutter.plugin.editing.TextInputPlugin; import io.flutter.plugin.editing.TextInputPlugin;
import io.flutter.plugin.platform.PlatformViewsController; import io.flutter.plugin.platform.PlatformViewsController;
...@@ -74,8 +75,10 @@ public class XFlutterView extends FrameLayout { ...@@ -74,8 +75,10 @@ public class XFlutterView extends FrameLayout {
// Internal view hierarchy references. // Internal view hierarchy references.
@Nullable @Nullable
private FlutterRenderer.RenderSurface renderSurface; private RenderSurface renderSurface;
private final Set<OnFirstFrameRenderedListener> onFirstFrameRenderedListeners = new HashSet<>();
private final Set<FlutterUiDisplayListener> flutterUiDisplayListeners = new HashSet<>();
private boolean didRenderFirstFrame; private boolean didRenderFirstFrame;
// Connections to a Flutter execution context. // Connections to a Flutter execution context.
...@@ -100,6 +103,9 @@ public class XFlutterView extends FrameLayout { ...@@ -100,6 +103,9 @@ public class XFlutterView extends FrameLayout {
private boolean hasAddFirstFrameRenderedListener=false; private boolean hasAddFirstFrameRenderedListener=false;
private boolean isFlutterUiDisplayed;
// Directly implemented View behavior that communicates with Flutter. // Directly implemented View behavior that communicates with Flutter.
private final FlutterRenderer.ViewportMetrics viewportMetrics = new FlutterRenderer.ViewportMetrics(); private final FlutterRenderer.ViewportMetrics viewportMetrics = new FlutterRenderer.ViewportMetrics();
...@@ -110,23 +116,32 @@ public class XFlutterView extends FrameLayout { ...@@ -110,23 +116,32 @@ public class XFlutterView extends FrameLayout {
} }
}; };
private final OnFirstFrameRenderedListener onFirstFrameRenderedListener = new OnFirstFrameRenderedListener() {
private final FlutterUiDisplayListener flutterUiDisplayListener = new FlutterUiDisplayListener() {
@Override @Override
public void onFirstFrameRendered() { public void onFlutterUiDisplayed() {
didRenderFirstFrame = true; isFlutterUiDisplayed = true;
for (OnFirstFrameRenderedListener listener : onFirstFrameRenderedListeners) { for (FlutterUiDisplayListener listener : flutterUiDisplayListeners) {
listener.onFirstFrameRendered(); listener.onFlutterUiDisplayed();
}
}
@Override
public void onFlutterUiNoLongerDisplayed() {
isFlutterUiDisplayed = false;
for (FlutterUiDisplayListener listener : flutterUiDisplayListeners) {
listener.onFlutterUiNoLongerDisplayed();
} }
} }
}; };
/** /**
* Constructs a {@code FlutterView} programmatically, without any XML attributes. * Constructs a {@code FlutterView} programmatically, without any XML attributes.
* <p> * <p>
* <ul> * <ul>
* <li>{@link #renderMode} defaults to {@link RenderMode#surface}.</li>
* <li>{@link #transparencyMode} defaults to {@link TransparencyMode#opaque}.</li>
* </ul> * </ul>
* {@code FlutterView} requires an {@code Activity} instead of a generic {@code Context} * {@code FlutterView} requires an {@code Activity} instead of a generic {@code Context}
* to be compatible with {@link PlatformViewsController}. * to be compatible with {@link PlatformViewsController}.
...@@ -202,7 +217,7 @@ public class XFlutterView extends FrameLayout { ...@@ -202,7 +217,7 @@ public class XFlutterView extends FrameLayout {
break; break;
case texture: case texture:
Log.v(TAG, "Internally using a FlutterTextureView."); Log.v(TAG, "Internally using a FlutterTextureView.");
XFlutterTextureView flutterTextureView = new XFlutterTextureView(getContext()); FlutterTextureView flutterTextureView = new FlutterTextureView(getContext());
renderSurface = flutterTextureView; renderSurface = flutterTextureView;
addView(flutterTextureView); addView(flutterTextureView);
break; break;
...@@ -233,20 +248,20 @@ public class XFlutterView extends FrameLayout { ...@@ -233,20 +248,20 @@ public class XFlutterView extends FrameLayout {
return didRenderFirstFrame; return didRenderFirstFrame;
} }
/**
* Adds the given {@code listener} to this {@code FlutterView}, to be notified upon Flutter's
* first rendered frame.
*/
public void addOnFirstFrameRenderedListener(@NonNull OnFirstFrameRenderedListener listener) { public void addOnFirstFrameRenderedListener(@NonNull FlutterUiDisplayListener listener) {
onFirstFrameRenderedListeners.add(listener); flutterUiDisplayListeners.add(listener);
} }
/** /**
* Removes the given {@code listener}, which was previously added with * Removes the given {@code listener}, which was previously added with
* {@link #addOnFirstFrameRenderedListener(OnFirstFrameRenderedListener)}. * {@link #addOnFirstFrameRenderedListener(FlutterUiDisplayListener)}.
*/ */
public void removeOnFirstFrameRenderedListener(@NonNull OnFirstFrameRenderedListener listener) { public void removeOnFirstFrameRenderedListener(@NonNull FlutterUiDisplayListener listener) {
onFirstFrameRenderedListeners.remove(listener); flutterUiDisplayListeners.remove(listener);
} }
//------- Start: Process View configuration that Flutter cares about. ------ //------- Start: Process View configuration that Flutter cares about. ------
...@@ -587,17 +602,11 @@ public class XFlutterView extends FrameLayout { ...@@ -587,17 +602,11 @@ public class XFlutterView extends FrameLayout {
} }
this.flutterEngine = flutterEngine; this.flutterEngine = flutterEngine;
// Instruct our FlutterRenderer that we are now its designated RenderSurface.
FlutterRenderer flutterRenderer = this.flutterEngine.getRenderer(); FlutterRenderer flutterRenderer = this.flutterEngine.getRenderer();
didRenderFirstFrame = flutterRenderer.hasRenderedFirstFrame(); isFlutterUiDisplayed = flutterRenderer.isDisplayingFlutterUi();
if(!hasAddFirstFrameRenderedListener){ renderSurface.attachToRenderer(flutterRenderer);
flutterRenderer.addOnFirstFrameRenderedListener(onFirstFrameRenderedListener); flutterRenderer.addIsDisplayingFlutterUiListener(flutterUiDisplayListener);
hasAddFirstFrameRenderedListener=true;
}
flutterRenderer.attachToRenderSurface(renderSurface);
// Initialize various components that know how to process Android View I/O
// in a way that Flutter understands.
if(textInputPlugin==null){ if(textInputPlugin==null){
...@@ -693,11 +702,17 @@ public class XFlutterView extends FrameLayout { ...@@ -693,11 +702,17 @@ public class XFlutterView extends FrameLayout {
// TODO(mattcarroll): once this is proven to work, move this line ot TextInputPlugin // TODO(mattcarroll): once this is proven to work, move this line ot TextInputPlugin
// Instruct our FlutterRenderer that we are no longer interested in being its RenderSurface. // Instruct our FlutterRenderer that we are no longer interested in being its RenderSurface.
FlutterRenderer flutterRenderer = flutterEngine.getRenderer(); FlutterRenderer flutterRenderer = flutterEngine.getRenderer();
// didRenderFirstFrame = false; isFlutterUiDisplayed = false;
flutterRenderer.removeOnFirstFrameRenderedListener(onFirstFrameRenderedListener); flutterRenderer.removeIsDisplayingFlutterUiListener(flutterUiDisplayListener);
flutterRenderer.detachFromRenderSurface(); flutterRenderer.stopRenderingToSurface();
flutterRenderer.setSemanticsEnabled(false);
renderSurface.detachFromRenderer();
flutterEngine = null; flutterEngine = null;
} }
public void release(){ public void release(){
if(textInputPlugin!=null){ if(textInputPlugin!=null){
......
...@@ -458,6 +458,11 @@ public class BoostFlutterActivity extends Activity ...@@ -458,6 +458,11 @@ public class BoostFlutterActivity extends Activity
// No-op. Hook for subclasses. // No-op. Hook for subclasses.
} }
@Override
public void cleanUpFlutterEngine(@NonNull FlutterEngine flutterEngine) {
}
@Override @Override
public boolean shouldAttachEngineToActivity() { public boolean shouldAttachEngineToActivity() {
......
...@@ -482,6 +482,11 @@ public class FlutterFragment extends Fragment implements FlutterActivityAndFragm ...@@ -482,6 +482,11 @@ public class FlutterFragment extends Fragment implements FlutterActivityAndFragm
} }
} }
@Override
public void cleanUpFlutterEngine(@NonNull FlutterEngine flutterEngine) {
}
/** /**
* See {@link NewEngineFragmentBuilder#shouldAttachEngineToActivity()} and * See {@link NewEngineFragmentBuilder#shouldAttachEngineToActivity()} and
* <p> * <p>
......
...@@ -17,9 +17,8 @@ import io.flutter.Log; ...@@ -17,9 +17,8 @@ import io.flutter.Log;
import io.flutter.embedding.android.FlutterView; import io.flutter.embedding.android.FlutterView;
import io.flutter.embedding.android.SplashScreen; import io.flutter.embedding.android.SplashScreen;
import io.flutter.embedding.engine.FlutterEngine; import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.renderer.OnFirstFrameRenderedListener; import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener;
import java.util.Date;
/** /**
* {@code View} that displays a {@link SplashScreen} until a given {@link FlutterView} * {@code View} that displays a {@link SplashScreen} until a given {@link FlutterView}
...@@ -57,39 +56,20 @@ public class FlutterSplashView extends FrameLayout { ...@@ -57,39 +56,20 @@ public class FlutterSplashView extends FrameLayout {
}; };
@NonNull @NonNull
private final OnFirstFrameRenderedListener onFirstFrameRenderedListener = new OnFirstFrameRenderedListener() { private final FlutterUiDisplayListener onFirstFrameRenderedListener = new FlutterUiDisplayListener() {
int i = 0;
@Override @Override
public void onFirstFrameRendered() { public void onFlutterUiDisplayed() {
if (FlutterBoost.instance().platform().whenEngineStart() == FlutterBoost.ConfigBuilder.FLUTTER_ACTIVITY_CREATED) {
long now = new Date().getTime();
long flutterPostFrameCallTime = FlutterBoost.instance().getFlutterPostFrameCallTime();
if (flutterPostFrameCallTime != 0 && (now - flutterPostFrameCallTime) > 800) {
if (splashScreen != null) { if (splashScreen != null) {
transitionToFlutter(); transitionToFlutter();
} }
return;
} }
handler.postDelayed(new Runnable() {
@Override @Override
public void run() { public void onFlutterUiNoLongerDisplayed() {
onFirstFrameRenderedListener.onFirstFrameRendered();
}
}, 200);
} else {
if (splashScreen != null) {
transitionToFlutter();
}
} }
}
}; };
@NonNull @NonNull
......
org.gradle.jvmargs=-Xmx1536M org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
\ No newline at end of file
...@@ -7,8 +7,11 @@ ...@@ -7,8 +7,11 @@
#import <Flutter/Flutter.h> #import <Flutter/Flutter.h>
NS_ASSUME_NONNULL_BEGIN
@interface GeneratedPluginRegistrant : NSObject @interface GeneratedPluginRegistrant : NSObject
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry; + (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry;
@end @end
NS_ASSUME_NONNULL_END
#endif /* GeneratedPluginRegistrant_h */ #endif /* GeneratedPluginRegistrant_h */
...@@ -3,7 +3,12 @@ ...@@ -3,7 +3,12 @@
// //
#import "GeneratedPluginRegistrant.h" #import "GeneratedPluginRegistrant.h"
#if __has_include(<flutter_boost/FlutterBoostPlugin.h>)
#import <flutter_boost/FlutterBoostPlugin.h> #import <flutter_boost/FlutterBoostPlugin.h>
#else
@import flutter_boost;
#endif
@implementation GeneratedPluginRegistrant @implementation GeneratedPluginRegistrant
......
...@@ -36,7 +36,9 @@ class _MyAppState extends State<MyApp> { ...@@ -36,7 +36,9 @@ class _MyAppState extends State<MyApp> {
return MaterialApp( return MaterialApp(
title: 'Flutter Boost example', title: 'Flutter Boost example',
builder: FlutterBoost.init(postPush: _onRoutePushed), builder: FlutterBoost.init(postPush: _onRoutePushed),
home: Container()); home: Container(
color:Colors.white
));
} }
void _onRoutePushed( void _onRoutePushed(
......
...@@ -240,6 +240,8 @@ static NSUInteger kInstanceCounter = 0; ...@@ -240,6 +240,8 @@ static NSUInteger kInstanceCounter = 0;
// }; // };
// NSMethodSignature * (*callSuper)(struct objc_super *, SEL, BOOL animated) = (__typeof__(callSuper))objc_msgSendSuper; // NSMethodSignature * (*callSuper)(struct objc_super *, SEL, BOOL animated) = (__typeof__(callSuper))objc_msgSendSuper;
// callSuper(&target, @selector(viewDidDisappear:), animated); // callSuper(&target, @selector(viewDidDisappear:), animated);
[self detatchFlutterEngine];
} }
- (void)installSplashScreenViewIfNecessary { - (void)installSplashScreenViewIfNecessary {
......
name: flutter_boost name: flutter_boost
description: A next-generation Flutter-Native hybrid solution. FlutterBoost is a Flutter plugin which enables hybrid integration of Flutter for your existing native apps with minimum efforts. description: A next-generation Flutter-Native hybrid solution. FlutterBoost is a Flutter plugin which enables hybrid integration of Flutter for your existing native apps with minimum efforts.
version: 0.1.61 version: 0.1.63
author: Alibaba Xianyu author: Alibaba Xianyu
homepage: https://github.com/alibaba/flutter_boost homepage: https://github.com/alibaba/flutter_boost
......
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