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
回答:官方的解决方案仅仅是在native侧对FlutterViewController和Flutterengine进行解耦,如此可以一个FlutterEngine切换不同的FlutterViewController或者Activity进行渲染。但其并未解决Native和Flutter页面混合的问题,无法保证两侧的页面生命周期一致。即使是Flutter官方针对这个问题也是建议使用FlutterBoost。
其差别主要有:
|*|FlutterBoost1.5 |Flutter官方方案 |其他框架|
|*|FlutterBoost2.0 |Flutter官方方案 |其他框架|
|----|----|----|----|
|是否支持混合页面之间随意跳转 |Y |N |Y|
|一致的页面生命周期管理(多Flutter页面) |Y |N |?|
|是否支持页面间数据传递(回传等) |Y |N |N|
|是否支持测滑手势 |Y |Y |Y|
|是否支持跨页的hero动画 |N |Y |N|
|是否支持跨页的hero动画 |Y |Y |N|
|内存等资源占用是否可控 |Y |Y |Y|
|是否提供一致的页面route方案 |Y |Y |N|
|iOS和Android能力及接口是否一致 |Y |N |N|
......@@ -94,3 +94,6 @@ VC设置横屏依赖于NavigationController或者rootVC。可以通过一下方
}
```
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;
import android.util.Log;
import com.idlefish.flutterboost.log.AndroidLog;
import com.idlefish.flutterboost.log.ILog;
public class Debuger {
private static final String TAG = "FlutterBoost#";
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) {
if(isDebug()) {
Log.e(TAG, info);
if (isDebug()) {
sLog.e(TAG, info);
}
}
......@@ -43,26 +49,50 @@ public class Debuger {
}
public static void exception(String message) {
if(isDebug()) {
if (canThrowError()) {
throw new RuntimeException(message);
}else{
Log.e(TAG,"exception",new RuntimeException(message));
} else {
sLog.e(TAG, "exception", new RuntimeException(message));
}
}
public static void exception(Throwable t) {
if(isDebug()) {
if (canThrowError()) {
throw new RuntimeException(t);
}else{
Log.e(TAG,"exception",t);
} else {
sLog.e(TAG, "exception", t);
}
}
public static boolean isDebug(){
public static boolean isDebug() {
try {
return FlutterBoost.instance().platform().isDebug();
}catch (Throwable t){
} catch (Throwable t) {
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;
import android.app.Application;
import android.content.Context;
import android.os.Bundle;
import android.os.Debug;
import androidx.annotation.NonNull;
import com.idlefish.flutterboost.interfaces.*;
import io.flutter.embedding.android.FlutterView;
......@@ -25,6 +27,7 @@ public class FlutterBoost {
private Activity mCurrentActiveActivity;
private boolean mEnterActivityCreate =false;
static FlutterBoost sInstance = null;
private static boolean sInit;
private long FlutterPostFrameCallTime = 0;
private Application.ActivityLifecycleCallbacks mActivityLifecycleCallbacks;
......@@ -45,7 +48,10 @@ public class FlutterBoost {
}
public void init(Platform platform) {
if (sInit){
Debuger.log("FlutterBoost is alread inited. Do not init twice");
return;
}
mPlatform = platform;
mManager = new FlutterViewContainerManager();
......@@ -144,7 +150,7 @@ public class FlutterBoost {
doInitialFlutter();
}
sInit = true;
}
......
package com.idlefish.flutterboost;
import android.os.Handler;
import android.util.Log;
import androidx.annotation.Nullable;
import com.idlefish.flutterboost.interfaces.IContainerRecord;
......@@ -212,7 +214,7 @@ public class FlutterBoostPlugin {
} catch (Throwable t) {
result.error("no flutter page found!", t.getMessage(), t);
result.error("no flutter page found!", t.getMessage(), Log.getStackTraceString(t));
}
}
break;
......@@ -231,7 +233,7 @@ public class FlutterBoostPlugin {
}
});
} catch (Throwable t) {
result.error("open page error", t.getMessage(), t);
result.error("open page error", t.getMessage(), Log.getStackTraceString(t));
}
}
break;
......@@ -244,7 +246,7 @@ public class FlutterBoostPlugin {
mManager.closeContainer(uniqueId, resultData, exts);
result.success(true);
} catch (Throwable t) {
result.error("close page error", t.getMessage(), t);
result.error("close page error", t.getMessage(), Log.getStackTraceString(t));
}
}
break;
......@@ -256,7 +258,7 @@ public class FlutterBoostPlugin {
mManager.onShownContainerChanged(newId, oldId);
result.success(true);
} catch (Throwable t) {
result.error("onShownContainerChanged", t.getMessage(), t);
result.error("onShownContainerChanged", t.getMessage(), Log.getStackTraceString(t));
}
}
break;
......
......@@ -802,6 +802,7 @@ public class XFlutterView extends FrameLayout {
+ "FlutterView was not attached to a FlutterEngine.");
return;
}
if(viewportMetrics.width==0&&viewportMetrics.height==0)return;
viewportMetrics.devicePixelRatio = getResources().getDisplayMetrics().density;
flutterEngine.getRenderer().setViewportMetrics(viewportMetrics);
......
package com.idlefish.flutterboost.containers;
import android.app.Activity;
import android.graphics.Color;
import android.view.*;
import androidx.lifecycle.Lifecycle;
import android.content.Context;
import android.content.Intent;
......@@ -10,9 +12,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
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.XFlutterView;
......@@ -253,20 +252,33 @@ public class FlutterFragment extends Fragment implements FlutterActivityAndFragm
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
configureStatusBarForFullscreenFlutterExperience();
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
public void onStart() {
super.onStart();
if (!isHidden()) {
delegate.onStart();
}
}
@Override
public void onResume() {
super.onResume();
if (!isHidden()) {
delegate.onResume();
}
}
// TODO(mattcarroll): determine why this can't be in onResume(). Comment reason, or move if possible.
@ActivityCallThrough
......@@ -277,14 +289,18 @@ public class FlutterFragment extends Fragment implements FlutterActivityAndFragm
@Override
public void onPause() {
super.onPause();
if (!isHidden()) {
delegate.onPause();
}
}
@Override
public void onStop() {
super.onStop();
if (!isHidden()) {
delegate.onStop();
}
}
@Override
public void onDestroyView() {
......@@ -300,6 +316,15 @@ public class FlutterFragment extends Fragment implements FlutterActivityAndFragm
delegate = null;
}
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (hidden) {
delegate.onPause();
} else {
delegate.onResume();
}
}
@ActivityCallThrough
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() {
TestWidgetsFlutterBinding.ensureInitialized();
test('test onMethodCall', () async {
FlutterBoost.singleton
.registerDefaultPageBuilder((pageName, params, _) => Container());
FlutterBoost.singleton.addContainerObserver(
(ContainerOperation operation, BoostContainerSettings settings) {});
FlutterBoost.singleton.addBoostContainerLifeCycleObserver(
(ContainerLifeCycle state, BoostContainerSettings settings) {});
FlutterBoost.singleton.addBoostNavigatorObserver(NavigatorObserver());
try {
FlutterBoost.singleton.open("url");
} catch (e) {
expect(e, isException);
}
try {
FlutterBoost.singleton.close("url");
} catch (e) {
expect(e, isNoSuchMethodError);
}
try {
FlutterBoost.singleton.closeCurrent(result: <String,dynamic>{}, exts: <String,dynamic>{});
} catch (e) {
expect(e, isNoSuchMethodError);
}
try {
FlutterBoost.singleton.closeByContext(null, result: <String,dynamic>{}, exts: <String,dynamic>{});
} catch (e) {
expect(e, isNoSuchMethodError);
}
});
// test('test onMethodCall', () async {
// FlutterBoost.singleton
// .registerDefaultPageBuilder((pageName, params, _) => Container());
// FlutterBoost.singleton.addContainerObserver(
// (ContainerOperation operation, BoostContainerSettings settings) {});
//
// FlutterBoost.singleton.addBoostContainerLifeCycleObserver(
// (ContainerLifeCycle state, BoostContainerSettings settings) {});
//
// FlutterBoost.singleton.addBoostNavigatorObserver(NavigatorObserver());
//
// try {
// FlutterBoost.singleton.open("url");
// } catch (e) {
// expect(e, isException);
// }
// try {
// FlutterBoost.singleton.close("url");
// } catch (e) {
// expect(e, isNoSuchMethodError);
// }
// try {
// FlutterBoost.singleton.closeCurrent(result: <String,dynamic>{}, exts: <String,dynamic>{});
// } catch (e) {
// expect(e, isNoSuchMethodError);
// }
//
// try {
// FlutterBoost.singleton.closeByContext(null, result: <String,dynamic>{}, exts: <String,dynamic>{});
// } catch (e) {
// 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