!android
Provider的核心實際上就是InheritedWidget,它其實是對InheritedWidget的封裝,讓InheritedWidget在數據管理上可以更加方便的被開發者所使用。編程
InheritedWidget 能實現全局的狀態更新,沒法解決局部的問題。segmentfault
首先繼承 ChangeNotifierapi
class BaseProvide with ChangeNotifier {
CompositeSubscription compositeSubscription = CompositeSubscription();
/// add [StreamSubscription] to [compositeSubscription]
///
/// 在 [dispose]的時候能進行取消
addSubscription(StreamSubscription subscription){
compositeSubscription.add(subscription);
}
@override
void dispose() {
super.dispose();
compositeSubscription.dispose();
}
}
class RegisterPageState extends State<RegisterPage>{
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => RegisterModel(),
child: switchStatusBar2DarkAppbar(
context: context,
title: "provider demo",
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ChildWidgetA(),
SizedBox(height: 24,),
ChildWidgetB()
],
),
)
)
);
}
}
class ChildWidgetA extends StatelessWidget {
@override
Widget build(BuildContext context) {
debugPrint('ChildWidgetA build');
var model = Provider.of<RegisterModel>(context);
return Container(
color: Colors.redAccent,
height: 108,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text('ChildA', style: new TextStyle(
color: Colors.black, fontSize: CommounUtil.getSp(15))),
Text('Model data: ${model.valueA}', style: new TextStyle(
color: Colors.black, fontSize: CommounUtil.getSp(15))),
RaisedButton(
onPressed: () => model.addA(),
child: Text('add'),
),
],
),
);
}
}
class ChildWidgetB extends StatelessWidget {
@override
Widget build(BuildContext context) {
debugPrint('ChildWidgetB build');
var model = Provider.of<RegisterModel>(context);
return Container(
color: Colors.blueAccent,
height: 108,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text('ChildB', style: new TextStyle(
color: Colors.black, fontSize: CommounUtil.getSp(15))),
Text('Model data: ${model.valueB}', style: new TextStyle(
color: Colors.black, fontSize: CommounUtil.getSp(15))),
RaisedButton(
onPressed: () => model.addB(),
child: Text('add'),
),
],
),
);
}
}
I/flutter (12301): ChildWidgetB build
I/flutter (12301): ChildWidgetA build
I/flutter (12301): ChildWidgetB build
I/flutter (12301): ChildWidgetA build
複製代碼
這種方式當viewmodel中有一個屬性發生變化時,A和B都會buildmarkdown
單個局部刷新Selector網絡
class ChildWidgetC extends StatelessWidget {
@override
Widget build(BuildContext context) {
debugPrint('ChildWidgetC build');
return Selector<RegisterModel, int>(
selector: (context, value) => value.valueA,
builder: (BuildContext context, value, Widget child) {
return Container(
color: Colors.redAccent,
height: 108,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text('ChildC',
style: new TextStyle(
color: Colors.black, fontSize: CommounUtil.getSp(15))),
Text('Model data: $value',
style: new TextStyle(
color: Colors.black, fontSize: CommounUtil.getSp(15))),
RaisedButton(
onPressed: () => context.read<RegisterModel>().addA(),
child: Text('add'),
),
],
),
);
});
}
}
class ChildWidgetD extends StatelessWidget {
@override
Widget build(BuildContext context) {
debugPrint('ChildWidgetD build');
return Container(
color: Colors.blueAccent,
height: 108,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text('ChildD',
style: new TextStyle(
color: Colors.black, fontSize: CommounUtil.getSp(15))),
Text('Model data: ${context.select((RegisterModel value) => value.valueB)}',
style: new TextStyle(
color: Colors.black, fontSize: CommounUtil.getSp(15))),
RaisedButton(
onPressed: () => context.read<RegisterModel>().addB(),
child: Text('add'),
),
],
),
);
}
}
複製代碼
有了Selector以後,就能夠在同一個數據模型中,根據條件,篩選出不一樣的刷新條件了,這樣就能夠避免數據模型中的某個屬性變換而引發的整個數據模型刷新了。app
詳細使用方法參考:pub.flutter-io.cn/packages/pr…框架
apiless
--http_util.dart ------------------dio網絡請求初始化封裝async
--net_util.dart ------------------get和post請求封裝
base
--app_channel.dart ------------------定義不一樣的開發環境
--app_config.dart ------------------不一樣的開發環境的地址
--base_provider.dart ------------------provider基類
--base_responce.dart ------------------接口返回的數據類型
--base_widge.dart ------------------基本控件封裝
--global_provider_manager.dart ------------------全局的model管理
common ------------------ 公共的方法
data ------------------ 接口數據解析
generated------------------國際化代碼
http ------------------接口地址
l10n ------------------字符串
--intl_en.arb 英文
--intl_zh.arb 中文
model------------------各個頁面請求model
--login_repository.dart
res
--colours.dart------------------顏色的定義
router
--application.dart------------------初始化router
--router_handers.dart------------------定義每一個頁面的路由
--routes.dart-----------------配置路由
ui------------------UI頁面
utils------------------工具類
viewmodel------------------每一個頁面的viewmodel
main_dev.dart,main_test.dart,main_uat.dart,main_online.dart
------------------不一樣開發環境的程序入口
class HttpUtil{
static HttpUtil instance;
Dio dio;
BaseOptions options;
static HttpUtil getInstance() {
print('getInstance');
if (instance == null) {
instance = new HttpUtil();
}
return instance;
}
HttpUtil() {
_initDio();
}
_initDio() {
final String token = AppConfig.appTools.getToken();
String baseRequestUrl=Channel.baseURL;
dio = new Dio()
..options = BaseOptions(
baseUrl: baseRequestUrl,
connectTimeout: 20000,
receiveTimeout: 20000)
..interceptors.add(HeaderInterceptor(token))
..interceptors.add(LogInterceptor(responseBody: true, requestBody: true));
}
}
class HeaderInterceptor extends Interceptor {
String token="";
HeaderInterceptor(String token){
this.token=token;
}
@override
onRequest(RequestOptions options) {
if (token != null && token.length > 0) {
options.headers.putIfAbsent('Authorization', () => 'Bearer' + ' ' + token);
}
return super.onRequest(options);
}
}
複製代碼
Stream<BaseResponce> get(String url, {Map<String, dynamic> params}) =>
Stream.fromFuture(_get(url, params: params)).asBroadcastStream();
Future<BaseResponce> _get(String url, {Map<String, dynamic> params}) async {
var response = await HttpUtil.getInstance().dio.get(url, queryParameters: params);
var res = BaseResponce.fromJson(response.data);
return res;
}
Stream<BaseResponce> post(String url,{dynamic body}) =>
Stream.fromFuture(_post(url, body)).asBroadcastStream();
Future<BaseResponce> _post(String url, dynamic body) async {
var response;
if(body==null){
response = await HttpUtil.getInstance().dio.post(url);
}else{
response = await HttpUtil.getInstance().dio.post(url, data: body);
}
var res = BaseResponce.fromJson(response.data);
if(res.code!=200){
}
return res;
}
複製代碼
詳細使用地址:pub.flutter-io.cn/packages/di…
默認會有一個main.dart文件
根據四個環境拷貝該文件並命名爲main_dev.dart,main_test.dart,main_uat.dart,main_online.dart
每一個文件初始化不一樣的渠道:
1.添加依賴配置
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.2 flutter_localizations: #國際化 sdk: flutter 複製代碼
2.MaterialApp的localizationsDelegates
MaterialApp(
// theme: ThemeData(
// //項目配置字體,其餘主題顏色配置的能夠百度
//// fontFamily: Theme.of(context).platform == TargetPlatform.android? (localModel.localeIndex == 1 ? "HanSans":"DIN") : "IOSGILROY",
// ),
debugShowCheckedModeBanner: false,
locale: localModel.locale,
//國際化工廠代理
localizationsDelegates: [
// Intl 插件(須要安裝) //S.of(context).title
S.delegate,
RefreshLocalizations.delegate, //下拉刷新
//系統控件 國際化
GlobalCupertinoLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate//文本方向等
],
supportedLocales: S.delegate.supportedLocales,
home: SpalshPage(),
),
複製代碼
3.使用本地化的值
安裝插件flutterIntl
重啓as,菜單欄的Tool下找到Flutter Intl 並選擇Initalize for the project
使用Add Locale
生成其餘語言的arb文件
使用S.of(context).autoBySystem 能夠獲取該字符串
1.導入依賴包
dependencies:
flutter:
sdk: flutter
# 路由跳轉框架 https://segmentfault.com/a/1190000022349982
fluro: "^1.6.3"
複製代碼
2.全局初始化
final router = new Router();///初始化路由
Routes.configureRoutes(router);
Application.router = router;
複製代碼
3.定義路由頁面
Handler homeHandler= Handler(handlerFunc: (BuildContext context, Map<String, List<String>> parameters){
return homePage();
});
Handler mineHandler= Handler(handlerFunc: (BuildContext context, Map<String, List<String>> parameters){
return minePage();
});
Handler loginHandler= Handler(handlerFunc: (BuildContext context, Map<String, List<String>> parameters){
return LoginPage();
});
Handler xieyiHandler= Handler(handlerFunc: (BuildContext context, Map<String, List<String>> parameters){
String type=parameters['type'].first;
return WebViewPage(type: type,);
});
Handler registerHandler= Handler(handlerFunc: (BuildContext context, Map<String, List<String>> parameters){
return RegisterPage();
});
複製代碼
4.配置路徑
class Routes{
static String home='/home';
static String mine='/mine';
static String login='/login';
static String xieyi='/xieyi/:type';
static String register='/register';
static void configureRoutes(Router router){
router.define(home, handler: homeHandler);
router.define(mine, handler: mineHandler);
router.define(login, handler: loginHandler);
router.define(xieyi, handler: xieyiHandler);
router.define(register, handler: registerHandler);
}
}
複製代碼
詳細使用地址:pub.flutter-io.cn/packages/fl…
響應式編程
簡單例子:
Rx.timer(1, new Duration(milliseconds: 700)).listen((event) {
requestPerMission(context);
});
複製代碼