Skip to content

Commit

Permalink
让容器数量决定Flutter的resume和pause状态,而不是前后台 (#1200)
Browse files Browse the repository at this point in the history
Co-authored-by: luckysmg <2539699336@qq.com>
  • Loading branch information
ColdPaleLight and luckysmg authored Jun 10, 2021
1 parent 99ed834 commit abc2598
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 37 deletions.
13 changes: 13 additions & 0 deletions android/src/main/java/com/idlefish/flutterboost/FlutterBoost.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.idlefish.flutterboost.containers.FlutterContainerManager;
import com.idlefish.flutterboost.containers.FlutterViewContainer;

import java.util.HashMap;
import java.util.Map;

import io.flutter.embedding.engine.FlutterEngine;
Expand All @@ -16,12 +17,17 @@

public class FlutterBoost {
public static final String ENGINE_ID = "flutter_boost_default_engine";
public static final String APP_LIFECYCLE_CHANGED_KEY = "app_lifecycle_changed_key";
public static final String LIFECYCLE_STATE = "lifecycleState";
public static final int FLUTTER_APP_STATE_RESUMED = 0;
public static final int FLUTTER_APP_STATE_PAUSED = 2;

private Activity topActivity = null;
private FlutterBoostPlugin plugin;
private boolean isBackForegroundEventOverridden = false;
private boolean isAppInBackground = false;


private FlutterBoost() {
}

Expand Down Expand Up @@ -222,6 +228,13 @@ public boolean isAppInBackground() {
isAppInBackground = inBackground;
}

public void changeFlutterAppLifecycle(int state) {
assert (state == FLUTTER_APP_STATE_PAUSED || state == FLUTTER_APP_STATE_RESUMED);
Map arguments = new HashMap();
arguments.put(LIFECYCLE_STATE, state);
sendEventToFlutter(APP_LIFECYCLE_CHANGED_KEY, arguments);
}

private class BoostActivityLifecycle implements Application.ActivityLifecycleCallbacks {
private int activityReferences = 0;
private boolean isActivityChangingConfigurations = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,28 +260,35 @@ public void onContainerHide(String uniqueId) {

public void onContainerCreated(FlutterViewContainer container) {
Log.v(TAG, "#onContainerCreated: " + container.getUniqueId());
FlutterContainerManager.instance().addContainer(container.getUniqueId(), container);
if (FlutterContainerManager.instance().getContainerSize() == 1) {
FlutterBoost.instance().changeFlutterAppLifecycle(FlutterBoost.FLUTTER_APP_STATE_RESUMED);
}
}

public void onContainerAppeared(FlutterViewContainer container) {
String uniqueId = container.getUniqueId();
FlutterContainerManager.instance().reorderContainer(uniqueId, container);
FlutterContainerManager.instance().activateContainer(uniqueId, container);
pushRoute(uniqueId, container.getUrl(), container.getUrlParams(), reply -> {});

onContainerShow(uniqueId);
Log.v(TAG, "#onContainerAppeared: " + uniqueId + ", " + FlutterContainerManager.instance().getContainers());
// Log.v(TAG, "#onContainerAppeared: " + uniqueId + ", " + FlutterContainerManager.instance().getContainers());
}

public void onContainerDisappeared(FlutterViewContainer container) {
String uniqueId = container.getUniqueId();
onContainerHide(uniqueId);
Log.v(TAG, "#onContainerDisappeared: " + uniqueId + ", " + FlutterContainerManager.instance().getContainers());
// Log.v(TAG, "#onContainerDisappeared: " + uniqueId + ", " + FlutterContainerManager.instance().getContainers());
}

public void onContainerDestroyed(FlutterViewContainer container) {
String uniqueId = container.getUniqueId();
removeRoute(uniqueId, reply -> {});
FlutterContainerManager.instance().removeContainer(uniqueId);
Log.v(TAG, "#onContainerDestroyed: " + uniqueId + ", " + FlutterContainerManager.instance().getContainers());
if (FlutterContainerManager.instance().getContainerSize() == 0) {
FlutterBoost.instance().changeFlutterAppLifecycle(FlutterBoost.FLUTTER_APP_STATE_PAUSED);
}
// Log.v(TAG, "#onContainerDestroyed: " + uniqueId + ", " + FlutterContainerManager.instance().getContainers());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package com.idlefish.flutterboost.containers;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class FlutterContainerManager {

private FlutterContainerManager() {}
private FlutterContainerManager() {
}

private static class LazyHolder {
static final FlutterContainerManager INSTANCE = new FlutterContainerManager();
}
Expand All @@ -15,7 +19,30 @@ public static FlutterContainerManager instance() {
return FlutterContainerManager.LazyHolder.INSTANCE;
}

private final Map<String, FlutterViewContainer> allContainers = new LinkedHashMap<>();
private final Map<String, FlutterViewContainer> allContainers = new HashMap<>();
private final LinkedList<FlutterViewContainer> activeContainers = new LinkedList<>();

public void addContainer(String uniqueId, FlutterViewContainer container) {
allContainers.put(uniqueId, container);

}

public void activateContainer(String uniqueId, FlutterViewContainer container) {
if (uniqueId == null || container == null) return;
assert (allContainers.containsKey(uniqueId));

if (activeContainers.contains(container)) {
activeContainers.remove(container);
}
activeContainers.add(container);
}

public void removeContainer(String uniqueId) {
if (uniqueId == null) return;
FlutterViewContainer container = allContainers.remove(uniqueId);
activeContainers.remove(container);
}


public FlutterViewContainer findContainerById(String uniqueId) {
if (allContainers.containsKey(uniqueId)) {
Expand All @@ -25,9 +52,8 @@ public FlutterViewContainer findContainerById(String uniqueId) {
}

public FlutterViewContainer getTopContainer() {
if (allContainers.size() > 0) {
LinkedList<String> listKeys = new LinkedList<String>(allContainers.keySet());
return allContainers.get(listKeys.getLast());
if (activeContainers.size() > 0) {
return activeContainers.getLast();
}
return null;
}
Expand All @@ -40,21 +66,7 @@ public boolean isTopContainer(String uniqueId) {
return false;
}

public void reorderContainer(String uniqueId, FlutterViewContainer container) {
if (uniqueId == null || container == null) return;
if (allContainers.containsKey(uniqueId)) {
allContainers.remove(uniqueId);
}
allContainers.put(uniqueId, container);
public int getContainerSize() {
return allContainers.size();
}

public void removeContainer(String uniqueId) {
if (uniqueId == null) return;
allContainers.remove(uniqueId);
}

public LinkedList<String> getContainers() {
return new LinkedList<String>(allContainers.keySet());
}

}
6 changes: 6 additions & 0 deletions example3.0/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,15 @@ void main() {
///添加全局生命周期监听类
PageVisibilityBinding.instance.addGlobalObserver(AppLifecycleObserver());

///这里的CustomFlutterBinding调用务必不可缺少,用于控制Boost状态的resume和pause
CustomFlutterBinding();
runApp(MyApp());
}

///创建一个自定义的Binding,集成和with的关系如下,里面什么都不用写
class CustomFlutterBinding extends WidgetsFlutterBinding
with BoostFlutterBinding {}

class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
Expand Down
2 changes: 0 additions & 2 deletions ios/Classes/container/FBFlutterViewContainer.m
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ - (void)bridge_viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
}
- (void)bridge_viewWillAppear:(BOOL)animated {
// [FLUTTER_APP inactive];
[FBLifecycle inactive ];
[super viewWillAppear:animated];
}
@end
Expand Down
1 change: 0 additions & 1 deletion ios/Classes/container/FBLifecycle.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,4 @@
@interface FBLifecycle : NSObject
+ (void)pause;
+ (void)resume;
+ (void)inactive;
@end
8 changes: 2 additions & 6 deletions ios/Classes/container/FBLifecycle.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,15 @@
@implementation FBLifecycle

+ (void)pause{
[[ENGINE lifecycleChannel] sendMessage:@"AppLifecycleState.paused"];
[[FlutterBoost instance]sendEventToFlutterWith:@"app_lifecycle_changed_key" arguments:@{@"lifecycleState":@2}];
if(ENGINE.viewController != nil){
// [(FBFlutterContainer *) ENGINE.viewController surfaceUpdated:NO];
ENGINE.viewController = nil;
}
}
+ (void)resume{
if([UIApplication sharedApplication].applicationState == UIApplicationStateActive){
[[ENGINE lifecycleChannel] sendMessage:@"AppLifecycleState.resumed"];
[[FlutterBoost instance]sendEventToFlutterWith:@"app_lifecycle_changed_key" arguments:@{@"lifecycleState":@0}];
}
}
+ (void)inactive{
[[ENGINE lifecycleChannel] sendMessage:@"AppLifecycleState.inactive"];
}

@end
3 changes: 0 additions & 3 deletions lib/boost_lifecycle_binding.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,11 @@ class BoostLifecycleBinding {
Logger.log('boost_lifecycle: BoostLifecycleBinding.appDidEnterForeground');
PageVisibilityBinding.instance
.dispatchPageForgroundEvent(container.topPage.route);

BoostFlutterBinding.instance.changeAppLifecycleState(AppLifecycleState.resumed);
}

void appDidEnterBackground(BoostContainer container) {
Logger.log('boost_lifecycle: BoostLifecycleBinding.appDidEnterBackground');
PageVisibilityBinding.instance
.dispatchPageBackgroundEvent(container.topPage.route);
BoostFlutterBinding.instance.changeAppLifecycleState(AppLifecycleState.paused);
}
}
40 changes: 40 additions & 0 deletions lib/flutter_boost_app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_boost/boost_channel.dart';
import 'package:flutter_boost/boost_flutter_binding.dart';

import 'boost_container.dart';
import 'boost_flutter_router_api.dart';
Expand Down Expand Up @@ -45,6 +46,8 @@ class FlutterBoostApp extends StatefulWidget {
}

class FlutterBoostAppState extends State<FlutterBoostApp> {
static const String _app_lifecycle_changed_key = "app_lifecycle_changed_key";

final Map<String, Completer<Object>> _pendingResult =
<String, Completer<Object>>{};

Expand All @@ -68,6 +71,8 @@ class FlutterBoostAppState extends State<FlutterBoostApp> {
final Map<String, List<EventListener>> _listenersTable =
<String, List<EventListener>>{};

VoidCallback _lifecycleStateListenerRemover;

@override
void initState() {
_containers.add(_createContainer(PageInfo(pageName: widget.initialRoute)));
Expand All @@ -80,15 +85,50 @@ class FlutterBoostAppState extends State<FlutterBoostApp> {
// overlayKey.currentState to load complete....
WidgetsBinding.instance.addPostFrameCallback((_) {
refresh();
_addAppLifecycleStateEventListener();
});

//setup the AppLifecycleState change event launched from native

// try to restore routes from host when hot restart.
assert(() {
_restoreStackForHotRestart();
return true;
}());
}

///Setup the AppLifecycleState change event launched from native
///Here,the [AppLifecycleState] is depends on the native container's num
///if container num >= 1,the state == [AppLifecycleState.resumed]
///else state == [AppLifecycleState.paused]
void _addAppLifecycleStateEventListener() {
_lifecycleStateListenerRemover = BoostChannel.instance
.addEventListener(_app_lifecycle_changed_key, (key, arguments) {
//we just deal two situation,resume and pause
//and 0 is resumed
//and 2 is paused

final int index = arguments["lifecycleState"];

if (index == AppLifecycleState.resumed.index) {
print("resume");
BoostFlutterBinding.instance
.changeAppLifecycleState(AppLifecycleState.resumed);
} else if (index == AppLifecycleState.paused.index) {
print("pause");
BoostFlutterBinding.instance
.changeAppLifecycleState(AppLifecycleState.paused);
}
return;
});
}

@override
void dispose() {
_lifecycleStateListenerRemover.call();
super.dispose();
}

@override
Widget build(BuildContext context) {
return widget.appBuilder(WillPopScope(
Expand Down

0 comments on commit abc2598

Please sign in to comment.