}
OK,现在我们可以愉悦的创建 Store 了。如下代码所示,在创建 Store 的同时,我们通过 initialState
对 GSYState 进行了初始化,然后通过 StoreProvider
加载了 Store 并且包裹了 MaterialApp
。 至此我们完成了 Redux 中的初始化构建。
void main() {
runApp(new FlutterReduxApp());
}
class FlutterReduxApp extends StatelessWidget {
/// 创建Store,引用 GSYState 中的 appReducer 创建 Reducer
/// initialState 初始化 State
final store = new Store(
appReducer,
initialState: new GSYState(
userInfo: User.empty(),
themeData: new ThemeData(
primarySwatch: GSYColors.primarySwatch,
),
locale: Locale(‘zh’, ‘CH’)),
);
FlutterReduxApp({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
/// 通过 StoreProvider 应用 store
return new StoreProvider(
store: store,
child: new MaterialApp(),
);
}
}
And then,接下来就是使用了。如下代码所示,通过在 build
中使用 StoreConnector
,通过 converter
转化 store.state 的数据,最后通过 builder
返回实际需要渲染的控件,这样就完成了数据和控件的绑定。当然,你也可以使用StoreBuilder
。
class DemoUseStorePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
///通过 StoreConnector 关联 GSYState 中的 User
return new StoreConnector<GSYState, User>(
///通过 converter 将 GSYState 中的 userInfo返回
converter: (store) => store.state.userInfo,
///在 userInfo 中返回实际渲染的控件
builder: (context, userInfo) {
return new Text(
userInfo.name,
);
},
);
}
}
最后,当你需要触发更新的时候,只需要如下代码即可。
StoreProvider.of(context).dispatch(new UpdateUserAction(newUserInfo));
So,或者简单的业务逻辑下,Redux 并没有什么优势,甚至显得繁琐。但是一旦框架搭起来,在复杂的业务逻辑下就会显示格外愉悦了。
二、主题
Flutter 中官方默认就支持主题设置,MaterialApp
提供了 theme
参数设置主题,之后可以通过 Theme.of(context)
获取到当前的 ThemeData
用于设置控件的颜色字体等。
ThemeData
的创建提供很多参数,这里主要说 primarySwatch
参数。 primarySwatch
是一个 MaterialColor 对象,内部由10种不同深浅的颜色组成,用来做主题色调再合适不过。
如下图和代码所示,Flutter 默认提供了很多主题色,同时我们也可以通过 MaterialColor
实现自定义的主题色。
MaterialColor primarySwatch = const MaterialColor(
primaryValue,
const <int, Color>{
50: const Color(primaryLightValue),
100: const Color(primaryLightValue),
200: const Color(primaryLightValue),
300: const Color(primaryLightValue),
400: const Color(primaryLightValue),
500: const Color(primaryValue),
600: const Color(primaryDarkValue),
700: const Color(primaryDarkValue),
800: const Color(primaryDarkValue),
900: const Color(primaryDarkValue),
},
);
那如何实现实时的主题切换呢?当然是通过 Redux 啦!
前面我们已经在 GSYState 中创建了 themeData
,此时将它设置给 MaterialApp 的 theme
参数,之后我们通过 dispatch 改变 themeData
即可实现主题切换。
注意,因为你的 MaterialApp 也是一个 StatefulWidget
,如下代码所示,还需要利用 StoreBuilder
包裹起来,之后我们就可以通过 dispatch
修改主题,通过 Theme.of(context).primaryColor
获取主题色啦。
@override
Widget build(BuildContext context) {
/// 通过 StoreProvider 应用 store
return new StoreProvider(
store: store,
child: new StoreBuilder(builder: (context, store) {
return new MaterialApp(
theme: store.state.themeData);
}),
);
}
····
ThemeData themeData = new ThemeData(primarySwatch: colors[index]);
store.dispatch(new RefreshThemeDataAction(themeData));
三、国际化
Flutter的国际化按照官网文件 internationalization 看起来稍微有些复杂,也没有提及实时切换,所以这里介绍下快速的实现。当然,少不了 Redux !
如上图所示大致流程,同样是通过默认 MaterialApp
设置,自定义的多语言需要实现的是: LocalizationsDelegate
和 Localizations
。最终流程会通过 Localizations
使用 Locale
加载这个 delegate
。所以我们要做的是:
- 实现 LocalizationsDelegate。
- 实现 Localizations。
- 通过 Store 的 Locale 切换语言。
如下代码所示,创建自定义 delegate 需要继承 LocalizationsDelegate
对象,其中主要实现 load
方法。我们可以是通过方法的 locale
参数,判断需要加载的语言,然后返回我们自定义好多语言实现类 GSYLocalizations
,最后通过静态 delegate
对外提供 LocalizationsDelegate
。
/**
- 多语言代理
- Created by guoshuyu
- Date: 2018-08-15
*/
class GSYLocalizationsDelegate extends LocalizationsDelegate {
GSYLocalizationsDelegate();
@override
bool isSupported(Locale locale) {
///支持中文和英语
return [‘en’, ‘zh’].contains(locale.languageCode);
}
///根据locale,创建一个对象用于提供当前locale下的文本显示
@override
Future load(Locale locale) {
return new SynchronousFuture(new GSYLocalizations(locale));
}
@override
bool shouldReload(LocalizationsDelegate old) {
return false;
}
///全局静态的代理
static GSYLocalizationsDelegate delegate = new GSYLocalizationsDelegate();
}
上面提到的 GSYLocalizations
其实是一个自定义对象,如下代码所示,它会根据创建时的 Locale
,通过 locale.languageCode
判断返回对应的语言实体:GSYStringBase的实现类。
因为 GSYLocalizations 对象最后会通过Localizations
加载,所以 Locale
也是在那时,通过 delegate 赋予。同时在该 context 下,可以通过Localizations.of
获取 GSYLocalizations,比如: GSYLocalizations.of(context).currentLocalized.app_name
。
///自定义多语言实现
class GSYLocalizations {
final Locale locale;
GSYLocalizations(this.locale);
///根据不同 locale.languageCode 加载不同语言对应
///GSYStringEn和GSYStringZh都继承了GSYStringBase
static Map<String, GSYStringBase> _localizedValues = {
‘en’: new GSYStringEn(),
‘zh’: new GSYStringZh(),
};
GSYStringBase get currentLocalized {
return _localizedValues[locale.languageCode];
}
///通过 Localizations 加载当前的 GSYLocalizations
///获取对应的 GSYStringBase
static GSYLocalizations of(BuildContext context) {
return Localizations.of(context, GSYLocalizations);
}
}
///语言实体基类
abstract class GSYStringBase {
String app_name;
}
///语言实体实现类
class GSYStringEn extends GSYStringBase {
@override
String app_name = “GSYGithubAppFlutter”;
}
///使用
GSYLocalizations.of(context).currentLocalized.app_name
说完了 delegate , 接下来就是 Localizations
了。在上面的流程图中可以看到, Localizations 提供一个 override
方法构建 Localizations
,这个方法中可以设置 locale,而我们需要的正是实时的动态切换语言显示。
如下代码,我们创建一个 GSYLocalizations
的 Widget,通过 StoreBuilder
绑定 Store,然后通过 Localizations.override
包裹我们需要构建的页面,将 Store 中的 locale
和 Localizations 的 locale
绑定起来。
class GSYLocalizations extends StatefulWidget {
final Widget child;
GSYLocalizations({Key key, this.child}) : super(key: key);
@override
State createState() {
return new _GSYLocalizations();
}
}
class _GSYLocalizations extends State {
@override
Widget build(BuildContext context) {
return new StoreBuilder(builder: (context, store) {
///通过 StoreBuilder 和 Localizations 实现实时多语言切换
return new Localizations.override(
context: context,
locale: store.state.locale,
child: widget.child,
);
});
}
}
如下代码,最后将 GSYLocalizations
使用到 MaterialApp
中。通过 store.dispatch
切换 Locale
即可。
@override
Widget build(BuildContext context) {
/// 通过 StoreProvider 应用 store
return new StoreProvider(
store: store,
child: new StoreBuilder(builder: (context, store) {
return new MaterialApp(
///多语言实现代理
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GSYLocalizationsDelegate.delegate,
],
locale: store.state.locale,
supportedLocales: [store.state.locale],
routes: {
HomePage.sName: (context) {
///通过 Localizations.override 包裹一层。—这里
return new GSYLocalizations(
child: new HomePage(),
);
},
});
}),
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
学习宝典
对我们开发者来说,一定要打好基础,随时准备战斗。不论寒冬是否到来,都要把自己的技术做精做深。虽然目前移动端的招聘量确实变少了,但中高端的职位还是很多的,这说明行业只是变得成熟规范起来了。竞争越激烈,产品质量与留存就变得更加重要,我们进入了技术赋能业务的时代。
不论遇到什么困难,都不应该成为我们放弃的理由!
很多人在刚接触这个行业的时候或者是在遇到瓶颈期的时候,总会遇到一些问题,比如学了一段时间感觉没有方向感,不知道该从那里入手去学习,对此我针对Android程序员,我这边给大家整理了一套学习宝典!包括不限于高级UI、性能优化、移动架构师、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
【算法合集】
【延伸Android必备知识点】
【Android部分高级架构视频学习资源】
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
[外链图片转存中…(img-9j7cf1SR-1712513409705)]
【算法合集】
[外链图片转存中…(img-wEI3xoVp-1712513409705)]
【延伸Android必备知识点】
[外链图片转存中…(img-fprXD7kZ-1712513409706)]
【Android部分高级架构视频学习资源】
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!