我正在制作一个应用,它有一个主题管理器、浅色模式、深色模式和系统模式。
我认为我用 redux 管理状态的方式,阻止了我用热重载来重载应用程序,我解释说: 如果我有一个带背景的脚手架,从themedata,如果thememode当前是暗的,并且背景颜色是Color(0xFF1F1F1F)(黑色阴影),我将其更改为Color(0xFFFFFFFF)(纯白色),然后我使用热重载,它不起作用,我需要通过热重启重新启动整个应用程序以查看更改。 与我的主题管理器一样,我使用单选按钮来管理它,如果我将主题更改为浅色或深色,则效果很好。
如果我将模式更改为系统,它可以正常工作,但是在打开应用程序的系统主题模式下,如果我更改手机的系统主题模式,则不起作用。在这种情况下 StoreProvider.dispatch 不起作用,store.dispatch 也不工作,我必须使用热重启。 这里是可能导致问题的代码。 main.dart:
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 的那个)中,themeData 值是正确的,如果我稍后使用与 Theme.of(context )(就像我在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);
答案 0 :(得分:1)
应用的 main()
或 initState()
方法的某些代码更改可能在热重新加载时在刷新后的 UI 中不可见。
作为一般规则,如果修改后的代码在根的下游
小部件的 build()
方法,然后热重载按预期运行。然而,
如果修改后的代码不会因为重建而重新执行
小部件树,那么在热重载后您将看不到它的效果。
这可能是热重载后主题数据更改未反映的原因,因为它是在应用程序的 main()
中定义的。
因此来自 Flutter 文档
<块引用>热重载将代码更改加载到虚拟机中并重新构建小部件
树,保留应用程序状态;它不会重新运行 main()
或
initState()
。
答案 1 :(得分:0)