diff --git a/.github/no-response.yml b/.github/no-response.yml new file mode 100644 index 0000000000000000000000000000000000000000..4c4562e917e16a47b845ea5da3ad8d9689de7617 --- /dev/null +++ b/.github/no-response.yml @@ -0,0 +1,17 @@ +# 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. diff --git a/CHANGELOG.md b/CHANGELOG.md index a29bef4c00e9f542809172aa470c4fec3ed5b4f0..568d3705b095f68177ba0234d1e24523209b4d51 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,14 @@ ios: iOS: no change +## 0.1.63 + + android: + Fixed bugs + + iOS: + no change + ### API changes From the point of API changes, we did some refactoring as following: #### iOS API changes diff --git a/Frequently Asked Question.md b/Frequently Asked Question.md new file mode 100644 index 0000000000000000000000000000000000000000..050909f43cea914faa64fed558b9491d679cbd88 --- /dev/null +++ b/Frequently Asked Question.md @@ -0,0 +1,46 @@ +### 在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 diff --git a/README.md b/README.md index 1ff4a314c7a2aaf15aa66ba6d1eb9f8839130b9f..784162511d1cc6243563817d5651a4ba202982a4 100755 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ # 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 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 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 - 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 - 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 flutter_boost: git: url: 'https://github.com/alibaba/flutter_boost.git' - ref: '0.1.61' + ref: '0.1.63' ``` androidx branch ```json 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: Please see the boost example for details. - +# FAQ +please read this document: +<a href="Frequently Asked Question.md">FAQ</a> # License diff --git a/README_CN.md b/README_CN.md index 788ad9e758561e4be82ff4f27f43b82196bf6d99..f863aee3d15c69b985c2da093e011c39d225f494 100755 --- a/README_CN.md +++ b/README_CN.md @@ -5,7 +5,7 @@ # 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 @@ -16,6 +16,10 @@ 在继ç»ä¹‹å‰ï¼Œæ‚¨éœ€è¦å°†Flutter集æˆåˆ°ä½ 现有的项目ä¸ã€‚flutter sdk çš„ç‰ˆæœ¬éœ€è¦ v1.9.1-hotfixes,å¦åˆ™ä¼šç¼–译失败. +# FAQ +è¯·é˜…è¯»è¿™ç¯‡æ–‡ç« : +<a href="Frequently Asked Question.md">FAQ</a> + # boost 版本说明 @@ -26,16 +30,16 @@ 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 的支æŒå£°æ˜Ž - ç›®å‰androidx 分支为 feature/flutter_1.9_androidx_upgrade + ç›®å‰androidx 分支为 v0.1.61-androidx-hotfixes 是基于flutter v1.9.1-hotfixes 分支,如果其他分支会编译错误 - å’Œ0.1.60代ç åŒæ¥ï¼ŒåŒæ—¶0.1.61çš„ bugfix 也会åˆå…¥è¯¥åˆ†æ”¯ã€‚ + å’Œ0.1.60代ç åŒæ¥ï¼Œ bugfix 也会åˆå…¥è¯¥åˆ†æ”¯ã€‚ @@ -52,7 +56,7 @@ support分支 flutter_boost: git: url: 'https://github.com/alibaba/flutter_boost.git' - ref: '0.1.61' + ref: '0.1.63' ``` @@ -61,7 +65,7 @@ androidx分支 flutter_boost: git: url: 'https://github.com/alibaba/flutter_boost.git' - ref: 'feature/flutter_1.9_androidx_upgrade' + ref: 'v0.1.61-androidx-hotfixes' ``` diff --git a/android/src/main/java/com/idlefish/flutterboost/FlutterBoost.java b/android/src/main/java/com/idlefish/flutterboost/FlutterBoost.java index b461419eb072e2c6317975f2ed2fa94c3b6c862a..35fdae60c3c007b3d6aff6df64e4a695926c64d9 100644 --- a/android/src/main/java/com/idlefish/flutterboost/FlutterBoost.java +++ b/android/src/main/java/com/idlefish/flutterboost/FlutterBoost.java @@ -29,6 +29,7 @@ public class FlutterBoost { static FlutterBoost sInstance = null; private long FlutterPostFrameCallTime = 0; + private Application.ActivityLifecycleCallbacks mActivityLifecycleCallbacks; public long getFlutterPostFrameCallTime() { return FlutterPostFrameCallTime; @@ -51,7 +52,7 @@ public class FlutterBoost { mPlatform = platform; mManager = new FlutterViewContainerManager(); - platform.getApplication().registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() { + mActivityLifecycleCallbacks = new Application.ActivityLifecycleCallbacks() { @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { @@ -123,7 +124,9 @@ public class FlutterBoost { mCurrentActiveActivity = null; } } - }); + }; + platform.getApplication().registerActivityLifecycleCallbacks(mActivityLifecycleCallbacks); + if (mPlatform.whenEngineStart() == ConfigBuilder.IMMEDIATELY) { @@ -231,10 +234,7 @@ public class FlutterBoost { return this; } - public ConfigBuilder whenEngineDestory(int whenEngineDestory) { - this.whenEngineDestory = whenEngineDestory; - return this; - } + public ConfigBuilder lifecycleListener(BoostLifecycleListener lifecycleListener) { this.lifecycleListener = lifecycleListener; @@ -271,10 +271,6 @@ public class FlutterBoost { return ConfigBuilder.this.whenEngineStart; } - @Override - public int whenEngineDestroy() { - return ConfigBuilder.this.whenEngineDestory; - } public FlutterView.RenderMode renderMode() { return ConfigBuilder.this.renderMode; diff --git a/android/src/main/java/com/idlefish/flutterboost/FlutterViewContainerManager.java b/android/src/main/java/com/idlefish/flutterboost/FlutterViewContainerManager.java index 6d87f974b3e61a2c577cc8a6086d251ae027a393..df677e12f92ea420e5d41e0ca5af9201042a9373 100755 --- a/android/src/main/java/com/idlefish/flutterboost/FlutterViewContainerManager.java +++ b/android/src/main/java/com/idlefish/flutterboost/FlutterViewContainerManager.java @@ -82,11 +82,9 @@ public class FlutterViewContainerManager implements IContainerManager { void removeRecord(IContainerRecord record) { mRecordStack.remove(record); mRecordMap.remove(record.getContainer()); - if(mRecordMap.isEmpty()){ - if( FlutterBoost.instance().platform().whenEngineDestroy()== FlutterBoost.ConfigBuilder.All_FLUTTER_ACTIVITY_DESTROY){ - FlutterBoost.instance().boostDestroy(); - } - } +// if(mRecordMap.isEmpty()){ +// +// } } diff --git a/android/src/main/java/com/idlefish/flutterboost/Platform.java b/android/src/main/java/com/idlefish/flutterboost/Platform.java index 2260d2287eca2ffdd5bbc84c27b2e9030c03d223..2d7227bd34a029e685727a4bc88aa7f4c3f27001 100644 --- a/android/src/main/java/com/idlefish/flutterboost/Platform.java +++ b/android/src/main/java/com/idlefish/flutterboost/Platform.java @@ -19,7 +19,6 @@ public abstract class Platform { public abstract int whenEngineStart(); - public abstract int whenEngineDestroy(); public abstract FlutterView.RenderMode renderMode(); @@ -39,7 +38,7 @@ public abstract class Platform { public void registerPlugins(PluginRegistry mRegistry) { - + if(pluginsRegister!=null){ pluginsRegister.registerPlugins(mRegistry); }else{ diff --git a/android/src/main/java/com/idlefish/flutterboost/XFlutterTextureView.java b/android/src/main/java/com/idlefish/flutterboost/XFlutterTextureView.java deleted file mode 100644 index b3b575059db3ccd857464a06434c266e62e1122d..0000000000000000000000000000000000000000 --- a/android/src/main/java/com/idlefish/flutterboost/XFlutterTextureView.java +++ /dev/null @@ -1,151 +0,0 @@ -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 diff --git a/android/src/main/java/com/idlefish/flutterboost/XFlutterView.java b/android/src/main/java/com/idlefish/flutterboost/XFlutterView.java index 169792621428217af49221721d35d6e2696c2d63..64ba0c4817c5e5fdf86a8b68276b9aa58937f79f 100644 --- a/android/src/main/java/com/idlefish/flutterboost/XFlutterView.java +++ b/android/src/main/java/com/idlefish/flutterboost/XFlutterView.java @@ -36,7 +36,8 @@ import io.flutter.Log; import io.flutter.embedding.android.*; import io.flutter.embedding.engine.FlutterEngine; 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.plugin.editing.TextInputPlugin; import io.flutter.plugin.platform.PlatformViewsController; @@ -74,8 +75,10 @@ public class XFlutterView extends FrameLayout { // Internal view hierarchy references. @Nullable - private FlutterRenderer.RenderSurface renderSurface; - private final Set<OnFirstFrameRenderedListener> onFirstFrameRenderedListeners = new HashSet<>(); + private RenderSurface renderSurface; + + private final Set<FlutterUiDisplayListener> flutterUiDisplayListeners = new HashSet<>(); + private boolean didRenderFirstFrame; // Connections to a Flutter execution context. @@ -100,6 +103,9 @@ public class XFlutterView extends FrameLayout { private boolean hasAddFirstFrameRenderedListener=false; + private boolean isFlutterUiDisplayed; + + // Directly implemented View behavior that communicates with Flutter. private final FlutterRenderer.ViewportMetrics viewportMetrics = new FlutterRenderer.ViewportMetrics(); @@ -110,23 +116,32 @@ public class XFlutterView extends FrameLayout { } }; - private final OnFirstFrameRenderedListener onFirstFrameRenderedListener = new OnFirstFrameRenderedListener() { + + private final FlutterUiDisplayListener flutterUiDisplayListener = new FlutterUiDisplayListener() { @Override - public void onFirstFrameRendered() { - didRenderFirstFrame = true; + public void onFlutterUiDisplayed() { + isFlutterUiDisplayed = true; - for (OnFirstFrameRenderedListener listener : onFirstFrameRenderedListeners) { - listener.onFirstFrameRendered(); + for (FlutterUiDisplayListener listener : flutterUiDisplayListeners) { + listener.onFlutterUiDisplayed(); + } + } + + @Override + public void onFlutterUiNoLongerDisplayed() { + isFlutterUiDisplayed = false; + + for (FlutterUiDisplayListener listener : flutterUiDisplayListeners) { + listener.onFlutterUiNoLongerDisplayed(); } } }; + /** * Constructs a {@code FlutterView} programmatically, without any XML attributes. * <p> * <ul> - * <li>{@link #renderMode} defaults to {@link RenderMode#surface}.</li> - * <li>{@link #transparencyMode} defaults to {@link TransparencyMode#opaque}.</li> * </ul> * {@code FlutterView} requires an {@code Activity} instead of a generic {@code Context} * to be compatible with {@link PlatformViewsController}. @@ -202,7 +217,7 @@ public class XFlutterView extends FrameLayout { break; case texture: Log.v(TAG, "Internally using a FlutterTextureView."); - XFlutterTextureView flutterTextureView = new XFlutterTextureView(getContext()); + FlutterTextureView flutterTextureView = new FlutterTextureView(getContext()); renderSurface = flutterTextureView; addView(flutterTextureView); break; @@ -233,20 +248,20 @@ public class XFlutterView extends FrameLayout { 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) { - onFirstFrameRenderedListeners.add(listener); + + + + + public void addOnFirstFrameRenderedListener(@NonNull FlutterUiDisplayListener listener) { + flutterUiDisplayListeners.add(listener); } /** * Removes the given {@code listener}, which was previously added with - * {@link #addOnFirstFrameRenderedListener(OnFirstFrameRenderedListener)}. + * {@link #addOnFirstFrameRenderedListener(FlutterUiDisplayListener)}. */ - public void removeOnFirstFrameRenderedListener(@NonNull OnFirstFrameRenderedListener listener) { - onFirstFrameRenderedListeners.remove(listener); + public void removeOnFirstFrameRenderedListener(@NonNull FlutterUiDisplayListener listener) { + flutterUiDisplayListeners.remove(listener); } //------- Start: Process View configuration that Flutter cares about. ------ @@ -587,17 +602,11 @@ public class XFlutterView extends FrameLayout { } this.flutterEngine = flutterEngine; - // Instruct our FlutterRenderer that we are now its designated RenderSurface. FlutterRenderer flutterRenderer = this.flutterEngine.getRenderer(); - didRenderFirstFrame = flutterRenderer.hasRenderedFirstFrame(); - if(!hasAddFirstFrameRenderedListener){ - flutterRenderer.addOnFirstFrameRenderedListener(onFirstFrameRenderedListener); - hasAddFirstFrameRenderedListener=true; - } - flutterRenderer.attachToRenderSurface(renderSurface); + isFlutterUiDisplayed = flutterRenderer.isDisplayingFlutterUi(); + renderSurface.attachToRenderer(flutterRenderer); + flutterRenderer.addIsDisplayingFlutterUiListener(flutterUiDisplayListener); - // Initialize various components that know how to process Android View I/O - // in a way that Flutter understands. if(textInputPlugin==null){ @@ -693,11 +702,17 @@ public class XFlutterView extends FrameLayout { // 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. + + FlutterRenderer flutterRenderer = flutterEngine.getRenderer(); -// didRenderFirstFrame = false; - flutterRenderer.removeOnFirstFrameRenderedListener(onFirstFrameRenderedListener); - flutterRenderer.detachFromRenderSurface(); + isFlutterUiDisplayed = false; + flutterRenderer.removeIsDisplayingFlutterUiListener(flutterUiDisplayListener); + flutterRenderer.stopRenderingToSurface(); + flutterRenderer.setSemanticsEnabled(false); + renderSurface.detachFromRenderer(); + flutterEngine = null; + } public void release(){ if(textInputPlugin!=null){ diff --git a/android/src/main/java/com/idlefish/flutterboost/containers/BoostFlutterActivity.java b/android/src/main/java/com/idlefish/flutterboost/containers/BoostFlutterActivity.java index 907cc4921b35cccc8512b2dcec08b2758c6cf05f..b5f35275ad89a86fb7467fc095eda2dd6c20a15b 100644 --- a/android/src/main/java/com/idlefish/flutterboost/containers/BoostFlutterActivity.java +++ b/android/src/main/java/com/idlefish/flutterboost/containers/BoostFlutterActivity.java @@ -458,6 +458,11 @@ public class BoostFlutterActivity extends Activity // No-op. Hook for subclasses. } + @Override + public void cleanUpFlutterEngine(@NonNull FlutterEngine flutterEngine) { + + } + @Override public boolean shouldAttachEngineToActivity() { diff --git a/android/src/main/java/com/idlefish/flutterboost/containers/FlutterFragment.java b/android/src/main/java/com/idlefish/flutterboost/containers/FlutterFragment.java index 31c1373abf1b8fc7fcd2ca7c450798a46df320fd..9b37ce86bcd6e8b3bb3dd65f2bd632517db08e98 100644 --- a/android/src/main/java/com/idlefish/flutterboost/containers/FlutterFragment.java +++ b/android/src/main/java/com/idlefish/flutterboost/containers/FlutterFragment.java @@ -482,6 +482,11 @@ public class FlutterFragment extends Fragment implements FlutterActivityAndFragm } } + @Override + public void cleanUpFlutterEngine(@NonNull FlutterEngine flutterEngine) { + + } + /** * See {@link NewEngineFragmentBuilder#shouldAttachEngineToActivity()} and * <p> diff --git a/android/src/main/java/com/idlefish/flutterboost/containers/FlutterSplashView.java b/android/src/main/java/com/idlefish/flutterboost/containers/FlutterSplashView.java index c7be37a8940d2c37466934fa4a474fbb5fc69178..52ba61b48567d21e79f03595d226082dff6337fd 100644 --- a/android/src/main/java/com/idlefish/flutterboost/containers/FlutterSplashView.java +++ b/android/src/main/java/com/idlefish/flutterboost/containers/FlutterSplashView.java @@ -17,9 +17,8 @@ import io.flutter.Log; import io.flutter.embedding.android.FlutterView; import io.flutter.embedding.android.SplashScreen; 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} @@ -57,39 +56,20 @@ public class FlutterSplashView extends FrameLayout { }; @NonNull - private final OnFirstFrameRenderedListener onFirstFrameRenderedListener = new OnFirstFrameRenderedListener() { - int i = 0; - + private final FlutterUiDisplayListener onFirstFrameRenderedListener = new FlutterUiDisplayListener() { @Override - public void onFirstFrameRendered() { - - 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) { - transitionToFlutter(); - } - return; - } - - handler.postDelayed(new Runnable() { - @Override - public void run() { - onFirstFrameRenderedListener.onFirstFrameRendered(); - } - }, 200); - - - } else { - if (splashScreen != null) { - transitionToFlutter(); - } + public void onFlutterUiDisplayed() { + if (splashScreen != null) { + transitionToFlutter(); } + } + @Override + public void onFlutterUiNoLongerDisplayed() { } + + }; @NonNull diff --git a/example/android/gradle.properties b/example/android/gradle.properties index 4d3226abc21bb47320bb73c654e77d565977204d..b029a83aa42e1fc9127e410c8dfb22c4862e53f9 100755 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -1,3 +1,5 @@ org.gradle.jvmargs=-Xmx1536M +android.enableR8=true + android.useAndroidX=true android.enableJetifier=true \ No newline at end of file diff --git a/example/ios/Runner/GeneratedPluginRegistrant.h b/example/ios/Runner/GeneratedPluginRegistrant.h index 3b700eb481958516658f91161adf8edcba2d72f2..ed9a5c61691e5335ceefc5106fb1e6cd73079609 100755 --- a/example/ios/Runner/GeneratedPluginRegistrant.h +++ b/example/ios/Runner/GeneratedPluginRegistrant.h @@ -7,8 +7,11 @@ #import <Flutter/Flutter.h> +NS_ASSUME_NONNULL_BEGIN + @interface GeneratedPluginRegistrant : NSObject + (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry; @end +NS_ASSUME_NONNULL_END #endif /* GeneratedPluginRegistrant_h */ diff --git a/example/ios/Runner/GeneratedPluginRegistrant.m b/example/ios/Runner/GeneratedPluginRegistrant.m index 76db25a458408b363a6d1503bc9a9dbc69ad83c6..ff6c110590ca78d4c1307378611c2f4f83553a62 100755 --- a/example/ios/Runner/GeneratedPluginRegistrant.m +++ b/example/ios/Runner/GeneratedPluginRegistrant.m @@ -3,7 +3,12 @@ // #import "GeneratedPluginRegistrant.h" + +#if __has_include(<flutter_boost/FlutterBoostPlugin.h>) #import <flutter_boost/FlutterBoostPlugin.h> +#else +@import flutter_boost; +#endif @implementation GeneratedPluginRegistrant diff --git a/example/lib/main.dart b/example/lib/main.dart index 3331ee9c5c57e3162391b3c812363aff34aac088..22058b4e6e608c1f09e99774dcdad11057500fe9 100755 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -36,7 +36,9 @@ class _MyAppState extends State<MyApp> { return MaterialApp( title: 'Flutter Boost example', builder: FlutterBoost.init(postPush: _onRoutePushed), - home: Container()); + home: Container( + color:Colors.white + )); } void _onRoutePushed( diff --git a/ios/Classes/container/FLBFlutterViewContainer.m b/ios/Classes/container/FLBFlutterViewContainer.m index af79b73fe8952874c9da6918f5f87ac16466d05e..947f36ecdd415442b7411e114a5480a71d3ba795 100755 --- a/ios/Classes/container/FLBFlutterViewContainer.m +++ b/ios/Classes/container/FLBFlutterViewContainer.m @@ -240,6 +240,8 @@ static NSUInteger kInstanceCounter = 0; // }; // NSMethodSignature * (*callSuper)(struct objc_super *, SEL, BOOL animated) = (__typeof__(callSuper))objc_msgSendSuper; // callSuper(&target, @selector(viewDidDisappear:), animated); + + [self detatchFlutterEngine]; } - (void)installSplashScreenViewIfNecessary { diff --git a/pubspec.yaml b/pubspec.yaml index fe048f692ac0df72cb25795256618c329a686bd7..44dec0f4720c3f6f0c3833a94180dde8005a4372 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ 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. -version: 0.1.61 +version: 0.1.63 author: Alibaba Xianyu homepage: https://github.com/alibaba/flutter_boost