http://www.lxweimin.com/p/cab2c1c2523f
Provide是Google官方推出的狀態管理模式。官方地址為:https://github.com/google/flutter-provide
現在Flutter的狀態管理方案很多,redux、bloc、state、Provide。
Scoped Model : 最早的狀態管理方案,我剛學Flutter的時候就使用的這個,雖然還有公司在用,但是大部分已經選用其它方案了。
Redux:現在國內用的最多,因為咸魚團隊一直在用,還出了自己fish redux。阿里宣布開源Flutter應用框架Fish Redux!
bloc:比Redux簡單,而且好用,特別是一個頁面里的狀態管理。
state:缺點是耦合太強,如果是大型應用,管理起來非常混亂。
Provide:是在Google的Github下的一個項目,剛出現不久,所以可以推測他是Google的親兒子。
要實現一個頁面狀態改變之后,另一個頁面狀態也隨之改變。效果圖如下:
效果圖
1、添加依賴
dependencies:
?provide: ^1.0.2
2、創建Provide
這個類似于創建一個state,但是為了跟State區分,我們叫創建Provide。新建一個provide文件夾,然后再里邊新建一個counter.dart 文件.代碼如下:
import 'package:flutter/material.dart';
class?Counter with ChangeNotifier {
?int value = 0;
?increment() {
?? ?value++;
?? ?notifyListeners();
?}
}
3、將狀態放入頂層
void main() {
?var counter =Counter();
?var providers = Providers();
? providers..provide(Provider<Counter>.value(counter));
?runApp(
?? ?ProviderNode(
????? child: MyApp(),
????? providers: providers,
?? ?)
?);
4、獲取狀態
class Number extends StatelessWidget {
?@override
? Widgetbuild(BuildContext context) {
?? ?return Container(
????? margin: EdgeInsets.only(top: 200.0),
????? child: Provide<Counter>(
??????? builder: (context, child,counter) {
???????? ?return Text('${counter.value}',style: TextStyle(fontSize: 30.0),);
?????? ?},
??? ??)
?? ?);
?}
}
builder方法接收三個參數
第一個參數context:代表上下文。
第二個參數child:假如這個小部件足夠復雜,內部有一些小部件是不會改變的,那么我們可以將這部分小部件寫在Provide的child屬性中,讓builder不再重復創建這些小部件,以提升性能。
第三個參數counter:這個參數代表了我們獲取的頂層providers中的狀態。
5、修改狀態
Widget build(BuildContext context) {
?? ?return Container(
????? child: Container(
??????? child: RaisedButton(
????????? onPressed: () {
??????????? Provide.value<Counter>(context).increment();
???????? ?},
????????? child: Text('增加'),
? ??????),
???? ?),
?? ?);
?}
作者:zda123000
鏈接:http://www.lxweimin.com/p/cab2c1c2523f
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
bloc:Flutter 基于BLoC完整Flutter App項目
http://www.lxweimin.com/p/be0107298bc5
2019.01.11 00:22:32字數 501閱讀 15,656
本項目包含啟動頁,引導頁,主題色,國際化,Bloc,RxDart。擁有較好的項目結構,比較規范的代碼。App擁有精致的UI界面,統一的交互,側滑退出,列表和Web界面均提供快速滾動至頂部功能。
作者初衷是為大家提供一個比較規范的Flutter項目示例。
有關項目最新動態,可以關注App內第一條Hot Item信息。
App目錄結構
|--lib
|-- blocs (bloc相關)
|-- common (常用類,例如常量Constant)
|-- data (網絡數據層)
|-- db (數據庫)
|-- event (事件類)
|-- models (實體類)
|-- res (資源文件,string,colors,dimens,styles)
|-- ui (界面相關page,dialog,widgets)
|-- utils (工具類)
data網絡數據層
|--data
|-- api (url字段)
|-- net (單例DioUtil)
|-- protocol (請求與返回實體類)
|-- repository (接口請求&解析)
api
classWanAndroidApi{/// 首頁banner http://www.wanandroid.com/banner/jsonstaticconstString BANNER="banner";staticconstString USER_REGISTER="user/register";//注冊staticconstString USER_LOGIN="user/login";//登錄staticconstString USER_LOGOUT="user/logout";//退出// 拼接urlstaticStringgetPath({String path:'',int page,String resType:'json'}){StringBuffer sb=newStringBuffer(path);if(page!=null){sb.write('/$page');}if(resType!=null&&resType.isNotEmpty){sb.write('/$resType');}returnsb.toString();}}
請求與返回實體類 protocol
classLoginReq{String username;String password;LoginReq(this.username,this.password);LoginReq.fromJson(Map<String,dynamic>json):username=json['username'],password=json['password'];Map<String,dynamic>toJson()=>{'username':username,'password':password,};@overrideStringtoString(){StringBuffer sb=newStringBuffer('{');sb.write("\"username\":\"$username\"");sb.write(",\"password\":$password");sb.write('}');returnsb.toString();}}
接口請求&解析 repository
classWanRepository{Future<List<BannerModel>>getBanner()async{BaseResp<List>baseResp=awaitDioUtil().request<List>(Method.get,WanAndroidApi.getPath(path:WanAndroidApi.BANNER));List<BannerModel>bannerList;if(baseResp.code!=Constant.STATUS_SUCCESS){returnnewFuture.error(baseResp.msg);}if(baseResp.data!=null){bannerList=baseResp.data.map((value){returnBannerModel.fromJson(value);}).toList();}returnbannerList;}}
資源文件 res
|--res
|-- colors.dart
|-- dimens.dart
|-- strings.dart
|-- styles.dart
colors.dart
classColours{staticconstColor app_main=Color(0xFF666666);staticconstColor text_dark=Color(0xFF333333);staticconstColor text_normal=Color(0xFF666666);staticconstColor text_gray=Color(0xFF999999);}
dimens.dart
classDimens{staticconstdoublefont_sp12=12;staticconstdoublefont_sp14=14;staticconstdoublefont_sp16=16;staticconstdoublegap_dp5=5;staticconstdoublegap_dp10=10;}
strings.dart
classIds{staticconstString titleHome='title_home';}Map<String,Map<String,Map<String,String>>>localizedValues={'en':{'US':{Ids.titleHome:'Home',}},'zh':{'CN':{Ids.titleHome:'主頁',},'HK':{Ids.titleHome:'主頁',},'TW':{Ids.titleHome:'主頁',}}};
styles.dart
classTextStyles{staticTextStyle listTitle=TextStyle(fontSize:Dimens.font_sp16,color:Colours.text_dark,fontWeight:FontWeight.bold,);staticTextStyle listContent=TextStyle(fontSize:Dimens.font_sp14,color:Colours.text_normal,);staticTextStyle listExtra=TextStyle(fontSize:Dimens.font_sp12,color:Colours.text_gray,);}//? 間隔classGaps{// 水平間隔staticWidget hGap5=newSizedBox(width:Dimens.gap_dp5);staticWidget hGap10=newSizedBox(width:Dimens.gap_dp10);// 垂直間隔staticWidget vGap5=newSizedBox(height:Dimens.gap_dp5);staticWidget vGap10=newSizedBox(height:Dimens.gap_dp10);}
Flutter 國際化相關
fluintl?是一個為應用提供國際化的庫,可快速集成實現應用多語言。該庫封裝了一個國際化支持類,通過提供統一方法getString(id)獲取字符串。
// 在MyApp initState配置多語言資源setLocalizedValues(localizedValues);//配置多語言資源// 在MaterialApp指定localizationsDelegates和supportedLocalesMaterialApp(home:MyHomePage(),localizationsDelegates:[GlobalMaterialLocalizations.delegate,GlobalWidgetsLocalizations.delegate,CustomLocalizations.delegate//設置本地化代理? ? ],supportedLocales:CustomLocalizations.supportedLocales,//設置支持本地化語言集合? ? );// 字符串獲取IntlUtil.getString(context,Ids.titleHome);CustomLocalizations.of(context).getString(StringIds.titleHome);
Flutter 屏幕適配?ScreenUtil
方案一、不依賴context
步驟1//如果設計稿尺寸默認配置一致,無需該設置。? 配置設計稿尺寸 默認 360.0 / 640.0 / 3.0setDesignWHD(_designW,_designH,_designD);步驟2// 在MainPageState build 調用MediaQuery.of(context)classMainPageStateextendsState<MainPage>{@overrideWidgetbuild(BuildContextcontext){// 在 MainPageState build 調用 MediaQuery.of(context)MediaQuery.of(context);returnnewScaffold(appBar:newAppBar(),);}}步驟3ScreenUtil.getInstance().screenWidthScreenUtil.getInstance().screenHeight//屏幕適配相關? ScreenUtil.getInstance().getWidth(size);//返回根據屏幕寬適配后尺寸(單位 dp or pt)ScreenUtil.getInstance().getHeight(size);//返回根據屏幕高適配后尺寸 (單位 dp or pt)ScreenUtil.getInstance().getWidthPx(sizePx);//sizePx 單位pxScreenUtil.getInstance().getHeightPx(sizePx);//sizePx 單位pxScreenUtil.getInstance().getSp(fontSize);//返回根據屏幕寬適配后字體尺寸
方案二、依賴context
//如果設計稿尺寸默認配置一致,無需該設置。? 配置設計稿尺寸 默認 360.0 / 640.0 / 3.0setDesignWHD(_designW,_designH,_designD);ScreenUtil.getScreenW(context);//屏幕 寬ScreenUtil.getScreenH(context);//屏幕 高//屏幕適配相關? ScreenUtil.getScaleW(context,size);//返回根據屏幕寬適配后尺寸(單位 dp or pt)ScreenUtil.getScaleH(context,size);//返回根據屏幕高適配后尺寸 (單位 dp or pt)ScreenUtil.getScaleSp(context,size);//返回根據屏幕寬適配后字體尺寸
Flutter 數據存儲??SpUtil
SpUtil : 單例"同步" SharedPreferences 工具類。
項目中為大家提供SpHelper,方便存取實體對象類。
// 存儲SplashModel實體對象SplashModelmodel=newSplashModel();SpHelper.putObject(Constant.KEY_SPLASH_MODEL,model);// 獲取SplashModel實體對象SplashModelmodel=SpHelper.getSplashModel();classSpHelper{// 存儲Obj,T 用于區分存儲類型staticvoidputObject<T>(Stringkey,Objectvalue){switch(T){caseint:SpUtil.putInt(key,value);break;casedouble:SpUtil.putDouble(key,value);break;casebool:SpUtil.putBool(key,value);break;caseString:SpUtil.putString(key,value);break;caseList:SpUtil.putStringList(key,value);break;default:SpUtil.putString(key,value==null?"":json.encode(value));break;}}staticSplashModelgetSplashModel(){String_splashModel=SpUtil.getString(Constant.KEY_SPLASH_MODEL);if(ObjectUtil.isNotEmpty(_splashModel)){MapuserMap=json.decode(_splashModel);returnSplashModel.fromJson(userMap);}returnnull;}}
主界面
啟動頁
側滑Back
快速滾動到頂部
分類頁面
國際化
主題色
我的?????? :?Flutter開源庫集合
GitHub :?flutter_wanandroid
APK??????? :點擊下載 v0.1.3
Android掃碼下載APK:
flutter_wanandroid
最后,如果您覺得不錯的話,來個Star吧!大家對該項目有好的意見或建議,歡迎反饋。反饋-->