android - 热重载不起作用,需要热重启Flutter
问题描述
我正在制作一个应用程序,它具有主题管理器、浅色模式、深色模式和系统模式。
我认为我用 redux 管理状态的方式,阻止我用 hot reload 重新加载应用程序,我解释:如果我有一个带背景的脚手架,从主题数据,如果主题模式当前是暗的,以及背景颜色是颜色(0xFF1F1F1F)(黑色阴影),我将其更改为颜色(0xFFFFFFFF)(纯白色),然后我使用热重载,它不起作用,我需要用热重启重新启动整个应用程序到看到变化。我的主题管理器也是如此,我使用单选按钮来管理它,如果我将主题更改为浅色或深色,它工作正常。
如果我将模式更改为系统,它可以正常工作,但是使用打开应用程序的系统主题模式,如果我更改手机的系统主题模式,它就不起作用。在这种情况下 StoreProvider.dispatch 不起作用, store.dispatch 也不起作用,我必须使用热重启。这里是可能导致问题的代码。主要飞镖:
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:async_redux/async_redux.dart';
import 'package:hive/hive.dart';
import 'package:app_name/Redux/States/AppState.dart';
import 'package:app_name/UI/Screens/AppHome.dart';
import 'package:app_name/Utilities/Themes.dart';
import 'package:app_name/Utilities/functions.dart';
import 'package:app_name/Utilities/extensions.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
Box box = await initHive();
SettingsState settingsState = SettingsState(
themeMode: box.get("theme").toString().themeModeFromString,
);
Store<AppState> store = Store(
initialState: AppState(settings: settingsState),
);
runApp(App(store: store));
}
class App extends StatelessWidget {
final Store<AppState> store;
App({
required this.store,
});
Widget build(BuildContext context) {
return StoreProvider<AppState>(
store: store,
child: StoreConnector<AppState, SettingsState>(
converter: (Store<AppState> store) => store.state.settings,
builder: (BuildContext context, SettingsState settings) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Carleo',
theme: lightTheme,
darkTheme: darkTheme,
themeMode: settings.themeMode,
home: Focus(
onFocusChange: (hasFocus) =>
SystemChrome.setEnabledSystemUIOverlays([]),
autofocus: true,
descendantsAreFocusable: true,
child: AppHome(),
),
);
},
),
);
}
}
这里是 AppHome.dart 文件:
import 'package:app_name/UI/Widgets/Radio%20buttons.dart';
import 'package:flutter/material.dart';
import 'package:carleo/UI/Screens/SelectAccess.dart';
import 'package:carleo/UI/Screens/Home.dart';
import 'package:carleo/UI/Widgets/CircularIndicator.dart';
import 'package:carleo/Utilities/Database Utilities.dart';
import 'package:app_name/Utilities/Themes.dart';
class AppHome extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: ThemeGetter.primary(context),
body: ThemeRadioButton(),
);
}
}
这里 Radio Buttons.dart:
import 'package:flutter/material.dart';
import 'package:async_redux/async_redux.dart';
import 'package:app_name/Redux/States/AppState.dart';
import 'package:app_name/Redux/Actions/Actions.dart';
class ThemeRadioButton extends StatelessWidget {
Widget build(BuildContext context) {
return StoreConnector<AppState, SettingsState>(
converter: (Store<AppState> store) => store.state.settings,
builder: (BuildContext context, SettingsState settings) {
return Wrap(
children: [
ListTile(
leading: Radio<ThemeMode>(
value: ThemeMode.light,
fillColor: MaterialStateProperty.all(Colors.black),
groupValue: settings.themeMode,
onChanged: (ThemeMode? mode) {
StoreProvider.dispatch<AppState>(
context,
ThemeChanger(
payload: mode ?? ThemeMode.light,
),
);
},
),
title: Text("Light"),
),
ListTile(
leading: Radio<ThemeMode>(
value: ThemeMode.dark,
fillColor: MaterialStateProperty.all(Colors.black),
groupValue: settings.themeMode,
onChanged: (ThemeMode? mode) {
StoreProvider.dispatch<AppState>(
context,
ThemeChanger(
payload: mode ?? ThemeMode.dark,
),
);
},
),
title: Text("Dark"),
),
ListTile(
leading: Radio<ThemeMode>(
value: ThemeMode.system,
fillColor: MaterialStateProperty.all(Colors.black),
groupValue: settings.themeMode,
onChanged: (ThemeMode? mode) {
StoreProvider.dispatch<AppState>(
context,
ThemeChanger(
payload: mode ?? ThemeMode.system,
),
);
},
),
title: Text("System"),
),
],
);
},
);
}
}
这里有任何其他可以帮助的事情:
ThemeData darkTheme = ThemeData(
backgroundColor: Color(0xFF1F1F1F),
accentColor: Color(0xFF101217),
primaryColor: Color(0xFFFFFFFF),
buttonColor: Color(0xFF0D47A1),
brightness: Brightness.dark,
);
ThemeData lightTheme = ThemeData(
backgroundColor: Color(0xFFFFFFFF),
accentColor: Color(0xFFFFFFFF),
brightness: Brightness.light,
);
class ThemeGetter {
static Color primary(BuildContext context) {
return Theme.of(context).backgroundColor;
}
static Color accent(BuildContext context) {
return Theme.of(context).accentColor;
}
static Color contrast(BuildContext context) {
return Theme.of(context).primaryColor;
}
static Color secondary(BuildContext context) {
return Theme.of(context).buttonColor;
}
}
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart' show ThemeMode;
extension StringEnumExtension on String {
ThemeMode get themeModeFromString => ThemeMode.values.firstWhere(
(e) => describeEnum(e) == this,
orElse: () => ThemeMode.system,
);
}
extension ThemeModeExtensions on ThemeMode {
String get name => describeEnum(this);
}
import 'package:flutter/material.dart' show ThemeMode;
class AppState {
final SettingsState settings;
AppState({SettingsState? settings})
: this.settings = settings ?? SettingsState();
AppState.copy({
required AppState state,
}) : this.settings = state.settings;
AppState copyWith({int? counter, SettingsState? settings}) => AppState(
settings: settings ?? this.settings,
);
@override
operator ==(Object another) =>
identical(this, another) ||
(another is AppState && this.settings == another.settings);
@override
int get hashCode => super.hashCode;
}
class SettingsState {
final ThemeMode themeMode;
SettingsState({
ThemeMode? themeMode,
}) : this.themeMode = themeMode ?? ThemeMode.system;
SettingsState.copy({
required SettingsState state,
}) : this.themeMode = state.themeMode;
SettingsState copyWith({ThemeMode? themeMode, ThemeMode? radioValue}) =>
SettingsState(
themeMode: themeMode ?? this.themeMode,
);
@override
operator ==(Object another) =>
identical(this, another) &&
(another is SettingsState && another.themeMode == this.themeMode);
@override
int get hashCode => super.hashCode;
}
import 'package:async_redux/async_redux.dart';
import 'package:flutter/material.dart' show ThemeMode;
import 'package:hive/hive.dart';
import 'package:carleo/Redux/States/AppState.dart';
import 'package:carleo/Utilities/extensions.dart';
class ThemeChanger extends ReduxAction<AppState> {
final ThemeMode payload;
ThemeChanger({
required this.payload,
});
@override
Future<AppState> reduce() async {
Box box = await Hive.openBox("Settings");
box.put("theme", payload.name);
return state.copyWith(
settings: state.settings.copyWith(
themeMode: payload,
),
);
}
}
任何帮助都将被接受。并提前感谢。
编辑:我注意到,即使 settings.themeMode 是 ThemeMode.system,并且在商店连接器(构建 MaterialApp 的那个)中,如果我稍后使用 Theme.of 相同的颜色,themeData 值也是正确的(上下文)(就像我在AppHome的脚手架背景做的那样),打印出来的颜色不对,是上次热重启的颜色。我将它放在 StoreConnector 构建器中以注意到:
Brightness brightness =
SchedulerBinding.instance!.window.platformBrightness;
bool darkModeOn = brightness == Brightness.dark;
print(settings.themeMode);
switch (settings.themeMode) {
case ThemeMode.light:
print(lightTheme.primaryColor);
break;
case ThemeMode.dark:
print(darkTheme.primaryColor);
break;
case ThemeMode.system:
if (darkModeOn)
print(darkTheme.primaryColor);
else
print(lightTheme.primaryColor);
}
只需这段代码即可注意到不同小部件中的颜色不同:
print(Theme.of(context).backgroundColor);
解决方案
main()
对应用程序或方法的某些代码更改initState()
可能在热重载时刷新的 UI 中不可见。
作为一般规则,如果修改后的代码位于根小部件
build()
方法的下游,则热重载会按预期运行。但是,如果修改后的代码由于重建窗口小部件树而不会重新执行,那么在热重载后您将看不到它的效果。
这可能是热重载后未反映主题数据更改的原因,因为它是在应用程序的main()
.
所以来自 Flutter 文档
热重载将代码更改加载到 VM 中并重新构建小部件树,保留应用程序状态;它不会重新运行
main()
或initState()
.
推荐阅读
- function - Svelte 虚拟列表组件 - 过滤列表后功能不起作用
- maven - Maven 的依赖:purge-local-repository 不会删除本地存储库
- javascript - 用子组件状态响应提交数据
- python-sphinx - Sphinx 文档中的人类可读迭代
- list-comprehension - 使用列表推导消除列表中包含另一个列表中的子字符串的字符串
- simulation - 如何在 SUMO 中改变边缘的交通流向?
- scala - 是否可以使用宏来修改生成的结构化类型实例调用代码?
- pdf - 使用 CA 服务设置服务器以验证我的组织发布的 PDF 的过程
- python - Tkinter 检查按钮在选中时更新,但在我取消选中时不更新
- wordpress - 如何使用模式 - WordPress