Commit 9961047f authored by justin's avatar justin

Merge branch 'master' into v1.12.13-hotfixes

parents 167f18c6 3f6a3da9
...@@ -45,13 +45,13 @@ bool isTopContainer = FlutterBoost.BoostContainer.of(context).onstage ...@@ -45,13 +45,13 @@ bool isTopContainer = FlutterBoost.BoostContainer.of(context).onstage
回答:官方的解决方案仅仅是在native侧对FlutterViewController和Flutterengine进行解耦,如此可以一个FlutterEngine切换不同的FlutterViewController或者Activity进行渲染。但其并未解决Native和Flutter页面混合的问题,无法保证两侧的页面生命周期一致。即使是Flutter官方针对这个问题也是建议使用FlutterBoost。 回答:官方的解决方案仅仅是在native侧对FlutterViewController和Flutterengine进行解耦,如此可以一个FlutterEngine切换不同的FlutterViewController或者Activity进行渲染。但其并未解决Native和Flutter页面混合的问题,无法保证两侧的页面生命周期一致。即使是Flutter官方针对这个问题也是建议使用FlutterBoost。
其差别主要有: 其差别主要有:
|*|FlutterBoost1.5 |Flutter官方方案 |其他框架| |*|FlutterBoost2.0 |Flutter官方方案 |其他框架|
|----|----|----|----| |----|----|----|----|
|是否支持混合页面之间随意跳转 |Y |N |Y| |是否支持混合页面之间随意跳转 |Y |N |Y|
|一致的页面生命周期管理(多Flutter页面) |Y |N |?| |一致的页面生命周期管理(多Flutter页面) |Y |N |?|
|是否支持页面间数据传递(回传等) |Y |N |N| |是否支持页面间数据传递(回传等) |Y |N |N|
|是否支持测滑手势 |Y |Y |Y| |是否支持测滑手势 |Y |Y |Y|
|是否支持跨页的hero动画 |N |Y |N| |是否支持跨页的hero动画 |Y |Y |N|
|内存等资源占用是否可控 |Y |Y |Y| |内存等资源占用是否可控 |Y |Y |Y|
|是否提供一致的页面route方案 |Y |Y |N| |是否提供一致的页面route方案 |Y |Y |N|
|iOS和Android能力及接口是否一致 |Y |N |N| |iOS和Android能力及接口是否一致 |Y |N |N|
...@@ -94,3 +94,6 @@ VC设置横屏依赖于NavigationController或者rootVC。可以通过一下方 ...@@ -94,3 +94,6 @@ VC设置横屏依赖于NavigationController或者rootVC。可以通过一下方
} }
``` ```
2. 改dart层:因为SystemChrome.setPreferredOrientations的设置是全局的,但混合栈是多页面,所以在main函数中设置,后面在新建一个FlutterViewController时会被冲掉。为了解决这个问题,需要在每个dart页面的build处都加上这语句来设置每个页面能支持哪些转向类型 2. 改dart层:因为SystemChrome.setPreferredOrientations的设置是全局的,但混合栈是多页面,所以在main函数中设置,后面在新建一个FlutterViewController时会被冲掉。为了解决这个问题,需要在每个dart页面的build处都加上这语句来设置每个页面能支持哪些转向类型
### 9. FlutterBoost for flutter1.12出现和surface相关的crash。可以参考这个issue:https://github.com/flutter/flutter/issues/52455
可能flutter engine的bug引起
...@@ -26,15 +26,21 @@ package com.idlefish.flutterboost; ...@@ -26,15 +26,21 @@ package com.idlefish.flutterboost;
import android.util.Log; import android.util.Log;
import com.idlefish.flutterboost.log.AndroidLog;
import com.idlefish.flutterboost.log.ILog;
public class Debuger { public class Debuger {
private static final String TAG = "FlutterBoost#"; private static final String TAG = "FlutterBoost#";
private static final Debuger DEBUG = new Debuger(); private static final Debuger DEBUG = new Debuger();
private static boolean sSafeMode = false;
private static ILog sLog = new AndroidLog();
private Debuger(){ } private Debuger() {
}
private void print(String info) { private void print(String info) {
if(isDebug()) { if (isDebug()) {
Log.e(TAG, info); sLog.e(TAG, info);
} }
} }
...@@ -43,26 +49,50 @@ public class Debuger { ...@@ -43,26 +49,50 @@ public class Debuger {
} }
public static void exception(String message) { public static void exception(String message) {
if(isDebug()) { if (canThrowError()) {
throw new RuntimeException(message); throw new RuntimeException(message);
}else{ } else {
Log.e(TAG,"exception",new RuntimeException(message)); sLog.e(TAG, "exception", new RuntimeException(message));
} }
} }
public static void exception(Throwable t) { public static void exception(Throwable t) {
if(isDebug()) { if (canThrowError()) {
throw new RuntimeException(t); throw new RuntimeException(t);
}else{ } else {
Log.e(TAG,"exception",t); sLog.e(TAG, "exception", t);
} }
} }
public static boolean isDebug(){ public static boolean isDebug() {
try { try {
return FlutterBoost.instance().platform().isDebug(); return FlutterBoost.instance().platform().isDebug();
}catch (Throwable t){ } catch (Throwable t) {
return false; return false;
} }
} }
/**
* 设置boost log接收实现,默认为Anroid自带Log
*
* @param log
*/
public static void setLog(ILog log) {
if (log != null) {
sLog = log;
}
}
/**
* 设置Debugger策略倾向,如tue,则优先保证程序稳定,false,可抛Error
*
* @param safeMode
*/
public static void setSafeMode(boolean safeMode) {
sSafeMode = safeMode;
}
private static boolean canThrowError() {
return isDebug() && !sSafeMode;
}
} }
...@@ -5,6 +5,8 @@ import android.app.Activity; ...@@ -5,6 +5,8 @@ import android.app.Activity;
import android.app.Application; import android.app.Application;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.os.Debug;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.idlefish.flutterboost.interfaces.*; import com.idlefish.flutterboost.interfaces.*;
import io.flutter.embedding.android.FlutterView; import io.flutter.embedding.android.FlutterView;
...@@ -25,6 +27,7 @@ public class FlutterBoost { ...@@ -25,6 +27,7 @@ public class FlutterBoost {
private Activity mCurrentActiveActivity; private Activity mCurrentActiveActivity;
private boolean mEnterActivityCreate =false; private boolean mEnterActivityCreate =false;
static FlutterBoost sInstance = null; static FlutterBoost sInstance = null;
private static boolean sInit;
private long FlutterPostFrameCallTime = 0; private long FlutterPostFrameCallTime = 0;
private Application.ActivityLifecycleCallbacks mActivityLifecycleCallbacks; private Application.ActivityLifecycleCallbacks mActivityLifecycleCallbacks;
...@@ -45,7 +48,10 @@ public class FlutterBoost { ...@@ -45,7 +48,10 @@ public class FlutterBoost {
} }
public void init(Platform platform) { public void init(Platform platform) {
if (sInit){
Debuger.log("FlutterBoost is alread inited. Do not init twice");
return;
}
mPlatform = platform; mPlatform = platform;
mManager = new FlutterViewContainerManager(); mManager = new FlutterViewContainerManager();
...@@ -144,7 +150,7 @@ public class FlutterBoost { ...@@ -144,7 +150,7 @@ public class FlutterBoost {
doInitialFlutter(); doInitialFlutter();
} }
sInit = true;
} }
......
package com.idlefish.flutterboost; package com.idlefish.flutterboost;
import android.os.Handler; import android.os.Handler;
import android.util.Log;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.idlefish.flutterboost.interfaces.IContainerRecord; import com.idlefish.flutterboost.interfaces.IContainerRecord;
...@@ -212,7 +214,7 @@ public class FlutterBoostPlugin { ...@@ -212,7 +214,7 @@ public class FlutterBoostPlugin {
} catch (Throwable t) { } catch (Throwable t) {
result.error("no flutter page found!", t.getMessage(), t); result.error("no flutter page found!", t.getMessage(), Log.getStackTraceString(t));
} }
} }
break; break;
...@@ -231,7 +233,7 @@ public class FlutterBoostPlugin { ...@@ -231,7 +233,7 @@ public class FlutterBoostPlugin {
} }
}); });
} catch (Throwable t) { } catch (Throwable t) {
result.error("open page error", t.getMessage(), t); result.error("open page error", t.getMessage(), Log.getStackTraceString(t));
} }
} }
break; break;
...@@ -244,7 +246,7 @@ public class FlutterBoostPlugin { ...@@ -244,7 +246,7 @@ public class FlutterBoostPlugin {
mManager.closeContainer(uniqueId, resultData, exts); mManager.closeContainer(uniqueId, resultData, exts);
result.success(true); result.success(true);
} catch (Throwable t) { } catch (Throwable t) {
result.error("close page error", t.getMessage(), t); result.error("close page error", t.getMessage(), Log.getStackTraceString(t));
} }
} }
break; break;
...@@ -256,7 +258,7 @@ public class FlutterBoostPlugin { ...@@ -256,7 +258,7 @@ public class FlutterBoostPlugin {
mManager.onShownContainerChanged(newId, oldId); mManager.onShownContainerChanged(newId, oldId);
result.success(true); result.success(true);
} catch (Throwable t) { } catch (Throwable t) {
result.error("onShownContainerChanged", t.getMessage(), t); result.error("onShownContainerChanged", t.getMessage(), Log.getStackTraceString(t));
} }
} }
break; break;
......
...@@ -802,6 +802,7 @@ public class XFlutterView extends FrameLayout { ...@@ -802,6 +802,7 @@ public class XFlutterView extends FrameLayout {
+ "FlutterView was not attached to a FlutterEngine."); + "FlutterView was not attached to a FlutterEngine.");
return; return;
} }
if(viewportMetrics.width==0&&viewportMetrics.height==0)return;
viewportMetrics.devicePixelRatio = getResources().getDisplayMetrics().density; viewportMetrics.devicePixelRatio = getResources().getDisplayMetrics().density;
flutterEngine.getRenderer().setViewportMetrics(viewportMetrics); flutterEngine.getRenderer().setViewportMetrics(viewportMetrics);
......
package com.idlefish.flutterboost.containers; package com.idlefish.flutterboost.containers;
import android.app.Activity; import android.app.Activity;
import android.graphics.Color;
import android.view.*;
import androidx.lifecycle.Lifecycle; import androidx.lifecycle.Lifecycle;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
...@@ -10,9 +12,6 @@ import androidx.annotation.NonNull; ...@@ -10,9 +12,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.idlefish.flutterboost.FlutterBoost; import com.idlefish.flutterboost.FlutterBoost;
import com.idlefish.flutterboost.XFlutterView; import com.idlefish.flutterboost.XFlutterView;
...@@ -253,20 +252,33 @@ public class FlutterFragment extends Fragment implements FlutterActivityAndFragm ...@@ -253,20 +252,33 @@ public class FlutterFragment extends Fragment implements FlutterActivityAndFragm
@Nullable @Nullable
@Override @Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
configureStatusBarForFullscreenFlutterExperience();
return delegate.onCreateView(inflater, container, savedInstanceState); return delegate.onCreateView(inflater, container, savedInstanceState);
} }
private void configureStatusBarForFullscreenFlutterExperience() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = this.getActivity().getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
window.getDecorView().setSystemUiVisibility(PlatformPlugin.DEFAULT_SYSTEM_UI | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
}
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
if (!isHidden()) {
delegate.onStart(); delegate.onStart();
} }
}
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
if (!isHidden()) {
delegate.onResume(); delegate.onResume();
} }
}
// TODO(mattcarroll): determine why this can't be in onResume(). Comment reason, or move if possible. // TODO(mattcarroll): determine why this can't be in onResume(). Comment reason, or move if possible.
@ActivityCallThrough @ActivityCallThrough
...@@ -277,14 +289,18 @@ public class FlutterFragment extends Fragment implements FlutterActivityAndFragm ...@@ -277,14 +289,18 @@ public class FlutterFragment extends Fragment implements FlutterActivityAndFragm
@Override @Override
public void onPause() { public void onPause() {
super.onPause(); super.onPause();
if (!isHidden()) {
delegate.onPause(); delegate.onPause();
} }
}
@Override @Override
public void onStop() { public void onStop() {
super.onStop(); super.onStop();
if (!isHidden()) {
delegate.onStop(); delegate.onStop();
} }
}
@Override @Override
public void onDestroyView() { public void onDestroyView() {
...@@ -300,6 +316,15 @@ public class FlutterFragment extends Fragment implements FlutterActivityAndFragm ...@@ -300,6 +316,15 @@ public class FlutterFragment extends Fragment implements FlutterActivityAndFragm
delegate = null; delegate = null;
} }
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (hidden) {
delegate.onPause();
} else {
delegate.onResume();
}
}
@ActivityCallThrough @ActivityCallThrough
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
......
package com.idlefish.flutterboost.log;
import android.util.Log;
public class AndroidLog implements ILog {
@Override
public void d(String tag, String msg) {
Log.d(tag, msg);
}
@Override
public void d(String tag, String msg, Throwable throwable) {
Log.d(tag, msg, throwable);
}
@Override
public void e(String tag, String msg) {
Log.e(tag, msg);
}
@Override
public void e(String tag, String msg, Throwable throwable) {
Log.e(tag, msg, throwable);
}
@Override
public void i(String tag, String msg) {
Log.i(tag, msg);
}
@Override
public void i(String tag, String msg, Throwable throwable) {
Log.i(tag, msg, throwable);
}
@Override
public void v(String tag, String msg) {
Log.v(tag, msg);
}
@Override
public void v(String tag, String msg, Throwable throwable) {
Log.v(tag, msg, throwable);
}
@Override
public void w(String tag, String msg) {
Log.w(tag, msg);
}
@Override
public void w(String tag, String msg, Throwable throwable) {
Log.w(tag, msg, throwable);
}
@Override
public boolean isLogLevelEnabled(int level) {
return true;
}
}
package com.idlefish.flutterboost.log;
public interface ILog {
public enum LogLevelEnum {
VERBOSE(0, "V"), DEBUG(1, "D"), INFO(2, "I"), WARNING(3, "W"), ERROR(4, "E");
private String logLevelName;
private int loglevel;
LogLevelEnum(int loglevel, String name) {
this.loglevel = loglevel;
this.logLevelName = name;
}
public String getLogLevelName() {
return logLevelName;
}
public int getLoglevel() {
return loglevel;
}
}
void d(String tag, String msg);
void d(String tag, String msg, Throwable throwable);
void e(String tag, String msg);
void e(String tag, String msg, Throwable throwable);
void i(String tag, String msg);
void i(String tag, String msg, Throwable throwable);
void v(String tag, String msg);
void v(String tag, String msg, Throwable throwable);
void w(String tag, String msg);
void w(String tag, String msg, Throwable throwable);
boolean isLogLevelEnabled(int level);
}
...@@ -8,37 +8,37 @@ void main() { ...@@ -8,37 +8,37 @@ void main() {
TestWidgetsFlutterBinding.ensureInitialized(); TestWidgetsFlutterBinding.ensureInitialized();
test('test onMethodCall', () async { // test('test onMethodCall', () async {
FlutterBoost.singleton // FlutterBoost.singleton
.registerDefaultPageBuilder((pageName, params, _) => Container()); // .registerDefaultPageBuilder((pageName, params, _) => Container());
FlutterBoost.singleton.addContainerObserver( // FlutterBoost.singleton.addContainerObserver(
(ContainerOperation operation, BoostContainerSettings settings) {}); // (ContainerOperation operation, BoostContainerSettings settings) {});
//
FlutterBoost.singleton.addBoostContainerLifeCycleObserver( // FlutterBoost.singleton.addBoostContainerLifeCycleObserver(
(ContainerLifeCycle state, BoostContainerSettings settings) {}); // (ContainerLifeCycle state, BoostContainerSettings settings) {});
//
FlutterBoost.singleton.addBoostNavigatorObserver(NavigatorObserver()); // FlutterBoost.singleton.addBoostNavigatorObserver(NavigatorObserver());
//
try { // try {
FlutterBoost.singleton.open("url"); // FlutterBoost.singleton.open("url");
} catch (e) { // } catch (e) {
expect(e, isException); // expect(e, isException);
} // }
try { // try {
FlutterBoost.singleton.close("url"); // FlutterBoost.singleton.close("url");
} catch (e) { // } catch (e) {
expect(e, isNoSuchMethodError); // expect(e, isNoSuchMethodError);
} // }
try { // try {
FlutterBoost.singleton.closeCurrent(result: <String,dynamic>{}, exts: <String,dynamic>{}); // FlutterBoost.singleton.closeCurrent(result: <String,dynamic>{}, exts: <String,dynamic>{});
} catch (e) { // } catch (e) {
expect(e, isNoSuchMethodError); // expect(e, isNoSuchMethodError);
} // }
//
try { // try {
FlutterBoost.singleton.closeByContext(null, result: <String,dynamic>{}, exts: <String,dynamic>{}); // FlutterBoost.singleton.closeByContext(null, result: <String,dynamic>{}, exts: <String,dynamic>{});
} catch (e) { // } catch (e) {
expect(e, isNoSuchMethodError); // expect(e, isNoSuchMethodError);
} // }
}); // });
} }
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