[toc]android
咱們以前粗略介紹了基礎以及佈局:git
Flutter從入門到奔潰(一):擼一個登陸界面github
Flutter從入門到奔潰(三):擼一個App基礎框架json
# Flutter從入門到奔潰(四):擼一個包含列表刷新以及網絡請求的首頁api
總算是脫離了無聊的靜態頁面,涉及到了一部分網絡交互,今天咱們接着進行UI交互的學習(由於開源中國的api感受不太好用,咱們改用wananzhuo的api,這個也是咱們安卓狗練手的必備項目了,這裏感謝鴻洋大神)。cookie
登陸界面使用咱們以前繪製的靜態頁面,在這裏咱們進行UI交互:網絡
接下來咱們分步進行上述操做:app
咱們頁面是用了基礎的TextField,因此咱們經過controller來進行數據獲取,(若是是用form表單的格式的話,還有另一種方式,在onsave方法裏面保存,這裏按下不表)。框架
onPressed: () {
_postLogin(
_userNameController.text, _userPassController.text);
},
複製代碼
咱們很容易能夠知道上述代碼的做用是經過2個對應的controller拿到了username,userpass2個參數,並把他們做爲參數提供給了私有方法*_postLogin*。
這裏對數據並無太大的要求,只要是非空,咱們就默認是有效數據,因此咱們作了簡單的判斷:
_postLogin(String userName, String userPassword) {
if (userName.isNotEmpty && userPassword.isNotEmpty) {
// do some
} else {
TsUtils.showShort('請輸入用戶名和密碼');
}
}
複製代碼
這裏咱們稍微講下使用的一個插件:** fluttertoast: ^2.0.7**,很明顯就是一個android的Toast方法,(這裏還有另一種作法是用原生提供橋接,讓flutter調用原生方法進行交互,這裏也按下不表,後續咱們更新這部分的內容),
import 'package:fluttertoast/fluttertoast.dart';
class TsUtils{
static showShort(String msg){
Fluttertoast.showToast(
msg: msg,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIos: 1,
bgcolor: "#63CA6C",
textcolor: '#ffffff'
);
}
}
複製代碼
玩安卓的api接口是典型的三段式接口:
{
"data": ...,
"errorCode": 0,
"errorMsg": ""
}
複製代碼
因此咱們對應進行了比較拙略的封裝:
// post請求
static Future<Map> post(String url,
{Map<String, String> params, bool saveCookie = false}) async {
if (params == null) {
params = new Map();
}
String _url = Api.BASE_URL + url;
if (OsApplication.cookie != null) {
params['Cookie'] = OsApplication.cookie;
}
http.Response res = await http.post(_url, body: params);
return _dealWithRes(res, saveCookie: saveCookie);
}
複製代碼
static Map<String, dynamic> _dealWithRes(var res, {bool saveCookie}) {
if (res.statusCode == 200) {
var cookie = res.headers['set-cookie'];
if (saveCookie) {
SpUtils.saveCookie(cookie);
OsApplication.cookie = cookie;
}
String body = res.body;
var jsonStr = json.decode(body);
print('the jsonStr is $jsonStr');
int errCode = jsonStr['errorCode'];
if (errCode == 0) {
var data = jsonStr['data'];
return data;
} else {
TsUtils.showShort(jsonStr['errorMsg']);
return null;
}
} else {
TsUtils.showShort('您的網絡好像不太好喲~~~///(^v^)\\\~~~');
return null;
}
}
複製代碼
這裏須要注意的是一個**cookie **,咱們用來進行登陸的憑證,這裏的思路是:
咱們完整的登陸方法應該是:
_postLogin(String userName, String userPassword) {
if (userName.isNotEmpty && userPassword.isNotEmpty) {
Map<String, String> params = new Map();
params['username'] = userName;
params['password'] = userPassword;
Http.post(Api.USER_LOGIN, params: params,saveCookie: true).then((result) {
SpUtils.map2UserInfo(result).then((userInfoBean){
if(userInfoBean!=null){
OsApplication.eventBus.fire(new LoginEvent(userInfoBean.username));
SpUtils.saveUserInfo(userInfoBean);
Navigator.pop(context);
}
});
});
} else {
TsUtils.showShort('請輸入用戶名和密碼');
}
}
複製代碼
這裏咱們是否是看到了一個熟悉的名詞呢=> eventBus,hahahahahahahahhahahahahhaha,它是咱們下一個步驟的主角。
咱們登陸後,要怎麼通知其餘頁面,我已經登陸了呢?
我以爲第二種比較划算!而在安卓中,咱們能夠經過原生的廣播,第三方的EventBus來實現,而在flutter,咱們能夠考慮用插件event_bus: ^1.0. 1來實現。
它的實現方式和安卓版的相似:
OsApplication.eventBus.fire(new LoginEvent(userInfoBean.username));
複製代碼
OsApplication.eventBus.on<LoginEvent>().listen((event) {
setState(() {
if (event != null && event.userName != null) {
userName = event.userName;
userAvatar = 'http://www.wanandroid.com/resources/image/pc/logo.png';
} else {
userName = null;
userAvatar = null;
}
});
});
複製代碼
這裏不能說用戶一點退出就立馬噌噌噌地退出了,要有一個交互的過程--AlertDialog,
_showDialog() {
showDialog(
builder: (context) => new AlertDialog(
title: new Text('提示'),
content: new Text('是否要退出登陸'),
actions: <Widget>[
new FlatButton(
onPressed: () {
Navigator.pop(context);
},
child: new Text('取消')),
new FlatButton(
onPressed: () {
SpUtils.cleanUserInfo();
OsApplication.eventBus.fire(new LoginEvent(null));
Navigator.pop(context);
},
child: new Text('是的'))
],
),
context: context);
}
複製代碼
在肯定按鈕中,咱們清除了用戶信息(包括保存保存於內存和持久化的userName,token,id,cookie), 而且發出了一個null的event,由接受源代碼能夠知道,會顯示未登陸狀態。
接下來作好準備!!! 你將會受到視覺的衝擊!!! 一大波鋼鐵直男的粗糙審美將會衝擊你! 我很自豪地認爲要是有審美選醜比賽,我確定能夠奪得第一!
一級頁面沒有什麼難度,咱們仍然有多種方案來實現它:
這裏咱們選用CustomScrollView,具體代碼能夠: 體系頁面 若是有人有興趣的話,能夠試試本身動手寫一個呢。
二級頁面用安卓來實現確定就是:tabLayout+ViewPager,有趣的是flutter只用一個控件就能夠實現了DefaultTabController
@override
Widget build(BuildContext context) {
widgetsUtils = new WidgetsUtils(context);
return new Scaffold(
appBar: new AppBar(
title: widgetsUtils.getAppBar(_title),
iconTheme: new IconThemeData(color: Colors.white),
),
body: new DefaultTabController(
child: new Scaffold(
appBar: new TabBar(
isScrollable: true,
tabs: _initTabs(),
),
body: new TabBarView(children: _initBody())),
length: classList.length,
),
);
}
複製代碼
其中的TabBar相似於tabLayout; 其中的TabBarView相似於ViewPager;
這裏有一個須要注意的點,TabBarView的children每次劃到的時候都會從新走一次initState(),而若是咱們在那裏請求接口的話,就會每次都請求一次,這樣不管是UI仍是性能仍是體驗都不是咱們要的 而解決方案是在children(也就是相似fragment)的State加上 with AutomaticKeepAliveClientMixin
class _SystemChildPageState extends State<SystemChildPage> with AutomaticKeepAliveClientMixin{
@override
bool get wantKeepAlive => true;
}
複製代碼
見名知意,這個是用於標誌是否保持狀態的tag。
三級沒了... 就一個webview
草草地說,好像也沒什麼好寫了,接下去作的都是重複性的勞動:
可是flutter不止這麼些能夠玩的,動畫,2端交互,其其餘他零零總總的,還有不少好玩的控件,嗯...接下來繼續慢慢玩flutter。
一塊兒玩吧