Skip to content

Commit f6900ea

Browse files
authored
Merge pull request #24 from MMMzq/dev
Dev
2 parents 49d62ba + c50da5c commit f6900ea

File tree

10 files changed

+159
-150
lines changed

10 files changed

+159
-150
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## [2.2.0]
2+
* 重构底层的实现方式以规避一些隐晦的bug
3+
4+
* Refactor the underlying implementation to avoid some hidden bugs
5+
16
## [2.1.1]
27
* showSimpleNotification和showNotification方法添加`onTap`,`onLongPress`参数
38

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ Loading|Text|CustomWidget
5151
#### 1. add dependencies into you project pubspec.yaml file
5252
``` dart
5353
dependencies:
54-
bot_toast: ^2.1.1
54+
bot_toast: ^2.2.0
5555
```
5656

5757
#### 2. import BotToast lib

README_zh.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ Loading|Text|CustomWidget
5555
#### 1. pubspec.yaml文件里添加依赖
5656
``` dart
5757
dependencies:
58-
bot_toast: ^2.1.0
58+
bot_toast: ^2.2.0
5959
```
6060

6161
#### 2. 导入BotToast库

example/android/gradle.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
org.gradle.jvmargs=-Xmx1536M
2+
android.enableR8=true

example/lib/main.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class EnterPage extends StatelessWidget {
4242
alignment: Alignment.topCenter,
4343
child: SingleChildScrollView(
4444
child: Container(
45-
margin: EdgeInsets.only(top: 5),
45+
margin: EdgeInsets.only(top: 30),
4646
child: Column(children: <Widget>[
4747
Text(
4848
"Notification",

lib/bot_toast.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ library bot_toast;
22

33
export 'src/basis.dart';
44
export 'src/bot_toast_init.dart' show BotToastInit;
5-
export 'src/toast.dart';
5+
export 'src/toast.dart' hide safeRun;
66
export 'src/toast_navigator_observer.dart';

lib/src/bot_toast_init.dart

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,32 @@
11
import 'package:flutter/material.dart';
22

3-
final GlobalKey<_BotToastInitState> botToastInitKey =
4-
GlobalKey<_BotToastInitState>();
3+
import 'bot_toast_manager.dart';
4+
5+
final GlobalKey<BotToastInitState> _botToastInitKey =
6+
GlobalKey<BotToastInitState>();
7+
8+
BotToastManager get botToastManager {
9+
assert(_botToastInitKey?.currentState?._botToastManager != null);
10+
return _botToastInitKey.currentState._botToastManager;
11+
}
512

613
class BotToastInit extends StatefulWidget {
714
final Widget child;
815

916
BotToastInit({@required this.child})
1017
: assert(child != null),
11-
super(key: botToastInitKey);
18+
super(key: _botToastInitKey);
1219

1320
@override
14-
_BotToastInitState createState() => _BotToastInitState();
21+
BotToastInitState createState() => BotToastInitState();
1522
}
1623

17-
class _BotToastInitState extends State<BotToastInit> {
24+
class BotToastInitState extends State<BotToastInit> {
1825
bool _needInit;
19-
2026
bool get needInit => _needInit;
2127

28+
BotToastManager _botToastManager;
29+
2230
void reset() {
2331
_needInit = false;
2432
}
@@ -32,9 +40,16 @@ class _BotToastInitState extends State<BotToastInit> {
3240
@override
3341
void initState() {
3442
_needInit = true;
43+
_botToastManager = BotToastManager(this);
3544
super.initState();
3645
}
3746

47+
@override
48+
void dispose() {
49+
_botToastManager.dispose();
50+
super.dispose();
51+
}
52+
3853
@override
3954
void didUpdateWidget(BotToastInit oldWidget) {
4055
_needInit = true;

lib/src/bot_toast_manager.dart

Lines changed: 120 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,146 @@
1+
import 'package:bot_toast/src/toast_widget/toast_widget.dart';
12
import 'package:flutter/material.dart';
3+
import '../bot_toast.dart';
4+
import 'bot_toast_init.dart';
5+
import 'toast.dart';
26

3-
class BotToastManager extends StatefulWidget {
4-
const BotToastManager({Key key}) : super(key: key);
57

6-
@override
7-
BotToastManagerState createState() => BotToastManagerState();
8-
}
8+
class BotToastManager {
9+
final Map<String, Map<UniqueKey, OverlayEntry>> _map = {};
10+
NavigatorState _navigatorState;
11+
BotToastNavigatorObserverProxy _observerProxy;
12+
BotToastInitState botToastInitState;
13+
14+
BotToastManager(this.botToastInitState);
915

10-
class BotToastManagerState extends State<BotToastManager> {
11-
final Map<String, Map<UniqueKey, IndexedSemantics>> _map = {};
12-
int index = 0;
1316

14-
@override
15-
Widget build(BuildContext context) {
16-
List<IndexedSemantics> children = _map.values.fold([], (value, items) {
17-
return value..addAll(items.values);
17+
void dispose() {
18+
if (_observerProxy != null) {
19+
BotToastNavigatorObserver.unregister(_observerProxy);
20+
}
21+
_children.forEach((item) {
22+
item.remove();
1823
});
19-
children.sort((a, b) => a.index.compareTo(b.index));
20-
return Stack(children: children);
24+
_children.clear();
2125
}
2226

23-
///这里不使用传进来的key,是因为该key在这里担当的是一个UUid的职责,
24-
///不应该用在widget里面,
25-
///那为什么有需要自己new 一个UniqueKey()
26-
///这表明这个Widget在这里面是独一无二的,
27-
///这会防止一些隐晦的bug,
28-
///例如:如果不加入该UniqueKey将会导致
29-
///[BotToast.showEnhancedWidget]onlyOne功能失效,
30-
///主要是因为flutter,只是根据runtimeType来进行判断的话
31-
///会导致调错了各个Toast的dispose
32-
void insert(String groupKey, UniqueKey key, Widget widget) {
33-
setState(() {
34-
_map[groupKey] ??= {};
35-
_map[groupKey][key] = IndexedSemantics(
36-
index: index++,
37-
child: widget,
38-
key: UniqueKey(),
27+
28+
///需要监听didPush是因为,当Navigator的Route集合为空再推一个Route会导致这个页面覆盖_BotToastManager上面,挡住了Toast,因此要手动移动到最后
29+
///在1.7.8版本以下,一般是在使用[Navigator.pushAndRemoveUntil]才可能发生这种情况
30+
void _checkNavigatorState(BuildContext context) {
31+
assert(BotToastNavigatorObserver.debugInitialization, """
32+
Please initialize properly!
33+
Example:
34+
BotToastInit(
35+
child: MaterialApp(
36+
title: 'BotToast Demo',
37+
navigatorObservers: [BotToastNavigatorObserver()],
38+
home: XxxPage()
39+
),
40+
);
41+
""");
42+
43+
void visitor(Element element) {
44+
assert(() {
45+
if (element.widget is Localizations &&
46+
((element as StatefulElement).state as dynamic).locale == null) {
47+
return false;
48+
}
49+
return true;
50+
}(), 'Initialization error : locale==null');
51+
if (element.widget is Navigator) {
52+
if (_navigatorState == null ||
53+
_navigatorState != (element as StatefulElement).state) {
54+
_navigatorState = (element as StatefulElement).state;
55+
}
56+
} else {
57+
element.visitChildElements(visitor);
58+
}
59+
}
60+
61+
context.visitChildElements(visitor);
62+
63+
assert(_navigatorState != null, '''
64+
Initialization error.
65+
The initialization method has been modified in version 2.0.
66+
do you wrapped you app widget like this?
67+
68+
BotToastInit(
69+
child: MaterialApp(
70+
navigatorObservers: [BotToastNavigatorObserver()],
71+
home: XxxPage(),
72+
),
73+
);
74+
''');
75+
76+
77+
78+
if (_observerProxy == null) {
79+
_observerProxy = BotToastNavigatorObserverProxy(
80+
didPush: (route, _) {
81+
if (route.isFirst && _children.isNotEmpty) {
82+
_navigatorState.overlay
83+
.rearrange(_children, below: _children.first);
84+
}
85+
},
3986
);
87+
BotToastNavigatorObserver.register(_observerProxy);
88+
}
89+
}
90+
91+
List<OverlayEntry> get _children =>
92+
_map.values.fold([], (value, items) {
93+
return value..addAll(items.values);
94+
});
95+
96+
97+
void insert(String groupKey, UniqueKey key, Widget widget) {
98+
_map[groupKey] ??= {};
99+
final uniqueKey = UniqueKey();
100+
final overlayEntry = OverlayEntry(builder: (_) =>
101+
ProxyDispose(key: uniqueKey, child: widget, disposeCallback: () {
102+
_map[groupKey]?.remove(key);
103+
},));
104+
_map[groupKey][key] = overlayEntry;
105+
safeRun(() {
106+
assert(botToastInitState != null);
107+
if (botToastInitState.needInit) {
108+
botToastInitState.reset();
109+
_checkNavigatorState(botToastInitState.context);
110+
}
111+
_navigatorState.overlay.insert(overlayEntry);
40112
});
41113
}
42114

43115
void remove(String groupKey, UniqueKey key) {
44-
setState(() {
45-
_map[groupKey]?.remove(key);
116+
safeRun(() {
117+
final result = _map[groupKey]?.remove(key);
118+
if (result != null) {
119+
result.remove();
120+
}
46121
});
47122
}
48123

49124
void removeAll(String groupKey) {
50-
setState(() {
125+
safeRun(() {
126+
_map[groupKey]?.forEach((key, value) {
127+
assert(value != null);
128+
value.remove();
129+
});
51130
_map[groupKey]?.clear();
52131
});
53132
}
54133

55134
void cleanAll() {
56-
setState(() {
135+
safeRun(() {
136+
List<OverlayEntry> children = _children;
137+
assert(children.every((test) => test != null));
138+
children.forEach((item) {
139+
item.remove();
140+
});
57141
_map.clear();
58142
});
59143
}
60144
}
145+
146+

0 commit comments

Comments
 (0)