Flutter32.Opensource China主介面My的網路請求校驗和資料封裝處理(04)
profile_page.dart主介面跳轉邏輯觸發,登入以後會通過EventBus跳轉到登入的處理eventBus.fire(LoginEvent());
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutterapp2/common/event_bus.dart';
import 'package:flutterapp2/constants/Constants.dart';
import 'package:flutterapp2/utils/data_utils.dart';
import 'login_web_page.dart';
/**
* 主介面My
*/
class ProfilePage extends StatefulWidget {
@override
_ProfilePageState createState() => _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage> {
List menuTitles = [
'我的訊息',
'閱讀記錄',
'我的部落格',
'我的問答',
'我的活動',
'我的團隊',
'邀請好友',
];
List menuIcons = [
Icons.message,
Icons.print,
Icons.error,
Icons.phone,
Icons.send,
Icons.people,
Icons.person,
];
String userAvatar;
String userName;
@override
void initState() {
// TODO: implement initState
super.initState();
//嘗試顯示使用者資訊
_showUerInfo();
eventBus.on<LoginEvent>().listen((event) {
//TODO
//獲取使用者資訊並顯示
});
eventBus.on<LogoutEvent>().listen((event) {
//TODO
});
}
_showUerInfo() {
}
@override
Widget build(BuildContext context) {
return ListView.separated(
itemBuilder: (context, index) {
//My介面的頭部
if(index == 0){
//頭像用Container裝起來
return _buildHeader();
}
index -= 1;
return ListTile(
leading: Icon(menuIcons[index]),
title: Text(menuTitles[index]),
trailing: Icon(Icons.arrow_forward_ios),//尾巴
onTap: () {
_login();
},
);
},
//分割線
separatorBuilder: (context, index) {
return Divider();
},
itemCount: menuTitles.length + 1
);
}
_login() async {
final result = await Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => LoginWebPage()));
if (result != null && result == 'refresh') {
print('Debug profile page LoginEvent');
//登入成功
eventBus.fire(LoginEvent());
}
}
Container _buildHeader() {
return Container(
height: 150.0,
color: Color(AppColors.APP_THEME),
//頭像的佈局填充
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
child: Container(
width: 60.0,
height: 60.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: Color(0xffffffff),
width: 2.0,
),
image: DecorationImage(
//載入網路圖片
image: AssetImage('assets/images/ic_avatar_default.png'),
fit: BoxFit.cover,
),
),
),
onTap: () {
//執行登入
_login();
},
),
SizedBox(
),
Text(
'點選頭像登入',
style: TextStyle(color: Color(0xffffffff)),
),
],
),
),
);
}
}
login_web_page.dart登入頁面跳轉邏輯,資料拼接組裝校驗,資料儲存完成以後會呼叫Navigator.pop(context, 'refresh');通過路由跳轉到My的介面
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
import 'package:flutterapp2/constants/Constants.dart';
import 'package:flutterapp2/utils/data_utils.dart';
import 'package:flutterapp2/utils/net_utils.dart';
class LoginWebPage extends StatefulWidget {
@override
_LoginWebPageState createState() => _LoginWebPageState();
}
class _LoginWebPageState extends State<LoginWebPage> {
FlutterWebviewPlugin _flutterWebviewPlugin = FlutterWebviewPlugin();
bool isLoading = true;
@override
void initState() {
// TODO: implement initState
super.initState();
//監聽url的變化
_flutterWebviewPlugin.onUrlChanged.listen((url) {
//https://www.oschina.net/action/oauth2/authorize?response_type=code&client_id=6i4Yu6IUqXnR64em0rsJ&redirect_uri=https://www.dongnaoedu.com/
print('Debug LoginWebPage onUrlChanged: $url');
if (mounted) {
setState(() {
isLoading = true;
});
}
if (url != null && url.length > 0 && url.contains('?code=')) {
//登入成功了
//提取授權碼code
String code = url.split('?')[1].split('&')[0].split('=')[1];
Map<String, dynamic> params = Map<String, dynamic>();
params['client_id'] = AppInfos.CLIENT_ID;
params['client_secret'] = AppInfos.CLIENT_SECRET;
params['grant_type'] = 'authorization_code';
params['redirect_uri'] = AppInfos.REDIRECT_URI;
params['code'] = '$code';
params['dataType'] = 'json';
NetUtils.get(AppUrls.OAUTH2_TOKEN, params).then((data) {
//{"access_token":"aa105aaf-ca4f-4458-822d-1ae6a1fa33f9","refresh_token":"daae8b80-3ca6-4514-a8ae-acb3a82c951c","uid":2006874,"token_type":"bearer","expires_in":510070}
//this is login_web_page: {"access_token":"d0e00aa3-4d43-4a05-ab76-546d351ce5d5","refresh_token":"555f4e8a-bccc-4976-9d7e-1d5183ef5798","uid":4571926,"token_type":"bearer","expires_in":604295}
print('Debug this is login_web_page: $data');
if (data != null) {
Map<String, dynamic> map = json.decode(data);
if (map != null && map.isNotEmpty) {
//儲存token等資訊
DataUtils.saveLoginInfo(map);
//彈出當前路由,並返回refresh通知我的介面重新整理資料
Navigator.pop(context, 'refresh');
}
}
});
}
});
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
_flutterWebviewPlugin.close();
}
@override
Widget build(BuildContext context) {
//authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https
List<Widget> _appBarTitle = [
Text(
'登入開源中國',
style: TextStyle(
color: Color(AppColors.APPBAR),
),
),
];
if(isLoading) {
_appBarTitle.add(SizedBox(
width: 10.0,
));
_appBarTitle.add(CupertinoActivityIndicator());
}
return WebviewScaffold(
url: AppUrls.OAUTH2_AUTHORIZE +
'?response_type=code&client_id=' +
AppInfos.CLIENT_ID +
'&redirect_uri=' +
AppInfos.REDIRECT_URI,
appBar: AppBar(
title: Row(
children: _appBarTitle,
),
),
withJavascript: true,//允許執行js
withLocalStorage: true,//允許本地儲存
withZoom: true,//允許網頁縮放
);
}
}
net_utils.dart網路資料的請求處理
import 'package:http/http.dart' as http;
class NetUtils{
//返回型別是String,是一個JSON
///authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz&redirect_uri
static Future<String> get(String url, Map<String, dynamic> params) async{
if(url != null && params != null && params.isNotEmpty) {
//拼裝引數
StringBuffer sb = StringBuffer('?');
params.forEach((key, value) {
sb.write('$key=$value&');
});
//去掉最後一個&
String paramStr = sb.toString().substring(0, sb.length - 1);
url += paramStr;
}
//NetUtils : https://www.oschina.net/action/openapi/token?client_id=6ZmjMJ4ZCW7YRhQ4sm42&client_secret=sXWCxyV1KegoF2gethYuBZhI8WQI9fjk&grant_type=authorization_code&redirect_uri=https://www.dongnaoedu.com/&code=1s8xBT&dataType=json
print('Debug NetUtils : $url');
http.Response response = await http.get(url);
return response.body;
}
}
data_utils.dart資料的封裝和拼接
import 'package:shared_preferences/shared_preferences.dart';
class DataUtils{
static const String SP_ACCESS_TOKEN = 'access_token';
static const String SP_REFRESH_TOKEN = 'refresh_token';
static const String SP_UID = 'uid';
static const String SP_TOKEN_TYPE = 'token_type';
static const String SP_EXPIRES_IN = 'expires_in';
static const String SP_IS_LOGIN = 'is_login';
//儲存資料
// {"access_token":"aa105aaf-ca4f-4458-822d-1ae6a1fa33f9","refresh_token":"daae8b80-3ca6-4514-a8ae-acb3a82c951c","uid":2006874,"token_type":"bearer","expires_in":510070}
static Future<void> saveLoginInfo(Map<String, dynamic> map) async {
if (map != null && map.isNotEmpty) {
SharedPreferences sp = await SharedPreferences.getInstance();
sp
..setString(SP_ACCESS_TOKEN, map[SP_ACCESS_TOKEN])
..setString(SP_REFRESH_TOKEN, map[SP_REFRESH_TOKEN])
..setInt(SP_UID, map[SP_UID])
..setString(SP_TOKEN_TYPE, map[SP_TOKEN_TYPE])
..setInt(SP_EXPIRES_IN, map[SP_EXPIRES_IN])
..setBool(SP_IS_LOGIN, true);
}
}
//清楚登陸資料
static Future<void> clearLoginInfo() async {
SharedPreferences sp = await SharedPreferences.getInstance();
sp
..setString(SP_ACCESS_TOKEN, '')
..setString(SP_REFRESH_TOKEN, '')
..setInt(SP_UID, -1)
..setString(SP_TOKEN_TYPE, '')
..setInt(SP_EXPIRES_IN, -1)
..setBool(SP_IS_LOGIN, false);
}
//是否登入
static Future<bool> isLogin() async {
SharedPreferences sp = await SharedPreferences.getInstance();
bool isLogin = sp.getBool(SP_IS_LOGIN);
return isLogin != null && isLogin;
}
//獲取token
static Future<String> getAccessToken() async {
SharedPreferences sp = await SharedPreferences.getInstance();
return sp.getString(SP_ACCESS_TOKEN);
}
}
使用EventBus和SharedPreferences需要在yaml檔案中
name: flutterapp2
description: A new Flutter application.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
sdk: ">=2.7.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.3
http: ^0.12.2
flutter_webview_plugin: ^0.3.11
shared_preferences: ^0.5.7+3
event_bus: ^1.1.1
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
assets:
#導航欄背景
- assets/images/ic_nav_news_normal.png
- assets/images/ic_nav_news_actived.png
- assets/images/ic_nav_tweet_normal.png
- assets/images/ic_nav_tweet_actived.png
- assets/images/ic_nav_discover_normal.png
- assets/images/ic_nav_discover_actived.png
- assets/images/ic_nav_my_normal.png
- assets/images/ic_nav_my_pressed.png
#抽屜背景
- assets/images/cover_img.jpg
#使用者預設頭像
- assets/images/ic_avatar_default.png
列印如下:
2020-10-08 23:58:40.324 17019-17246/com.example.flutterapp2 I/flutter: Debug LoginWebPage onUrlChanged: https://www.oschina.net/action/oauth2/authorize?response_type=code&client_id=6ZmjMJ4ZCW7YRhQ4sm42&redirect_uri=https://www.dongnaoedu.com/
2020-10-08 23:58:54.658 17019-17246/com.example.flutterapp2 I/flutter: Debug LoginWebPage onUrlChanged: https://www.dongnaoedu.com/?code=Jsl6Yh&state=#
2020-10-08 23:58:54.668 17019-17246/com.example.flutterapp2 I/flutter: Debug NetUtils : https://www.oschina.net/action/openapi/token?client_id=6ZmjMJ4ZCW7YRhQ4sm42&client_secret=sXWCxyV1KegoF2gethYuBZhI8WQI9fjk&grant_type=authorization_code&redirect_uri=https://www.dongnaoedu.com/&code=Jsl6Yh&dataType=json
2020-10-08 23:58:55.241 17019-17246/com.example.flutterapp2 I/flutter: Debug this is login_web_page: {"access_token":"21b8d7d0-6bef-469f-ba64-033d47387d50","refresh_token":"45545f98-d72c-4b3e-b6bd-f2f037f0a661","uid":4571926,"token_type":"bearer","expires_in":603334}
2020-10-08 23:58:55.252 17019-17246/com.example.flutterapp2 I/flutter: Debug profile page LoginEvent
效果如下:
相關文章
- 基於FutureBuilder通用網路請求介面封裝Rebuild封裝
- OC:封裝網路請求封裝
- Flutter 網路請求框架封裝Flutter框架封裝
- 小程式-網路請求封裝封裝
- Flutter 網路請求 Dio 封裝Flutter封裝
- uni-app網路請求的封裝APP封裝
- 請求資料處理
- 十. Axios網路請求封裝iOS封裝
- 13封裝網路請求類庫封裝
- 封裝springmvc處理ajax請求結果封裝SpringMVC
- fetch資料請求的封裝封裝
- 通過Handler封裝的網路請求資料的工具類NetUtils封裝
- axios 請求資料封裝iOS封裝
- flutter dio網路請求封裝實現Flutter封裝
- react中請求介面的封裝React封裝
- .NET處理HTTP請求——摘自網路HTTP
- 封裝axios請求並對提交引數進行校驗封裝iOS
- Retrofit2/Rxkotlin網路請求的封裝Kotlin封裝
- iOS for 迴圈內網路請求的處理iOS內網
- 網路資料請求
- [譯]使用 Siesta 處理 Swift 網路請求Swift
- 使用GCD實現和封裝分組併發網路請求GC封裝
- Retrofit+okhttp+Rxjava封裝網路請求工具類HTTPRxJava封裝
- 微信小程式之網路請求簡單封裝微信小程式封裝
- Kotlin中Retrofit網路請求簡單封裝Kotlin封裝
- iOS資料請求超時處理iOS
- vue+axois 封裝請求+攔截器(請求鎖+統一處理錯誤碼)Vue封裝
- Flutter 熱門網路請求框架Dio的簡單封裝Flutter框架封裝
- Retrofit + Kotlin + MVVM 的網路請求框架的封裝嘗試KotlinMVVM框架封裝
- RxRetrofit-終極封裝-深入淺出&網路請求封裝
- KafkaClient介面與Kafka處理請求的若干特性Kafkaclient
- 基於小程式請求介面 wx.request 封裝的類 axios 請求封裝iOS
- Retrofit2.5怎麼做到網路請求的處理的?
- swift網路資料請求方法Swift
- 關於對小程式網路請求的封裝(詳盡版)封裝
- Retrofit + RxJava + OkHttp 讓網路請求變的簡單-封裝篇RxJavaHTTP封裝
- fastapi 請求引數 校驗ASTAPI
- NUXT3.0實現網路請求二次封裝UX封裝