3.Flutter开发玩安卓app-网络请求及全局状态管理

网络请求开始

前言
网络请求,我们得先知道网络请求的地址对吧,先来我们玩安卓看一下玩安卓开放api
问题
这里讲一下我自己使用玩安卓api实现的时候遇到的问题,主要问题就是登陆后cookies的存储

5.1 登录
https://www.wanandroid.com/user/login

方法:POST
参数:
    username,password
登录后会在cookie中返回账号密码,只要在客户端做cookie持久化存储即可自动登录验证。

玩安卓的认证方式是采用cookies,所以就涉及到我们客户端如何存储cookies,然后现有flutter中有哪些能用的库方便我们操作

网络请求及cookies存储

  • 首先网络请求我使用的是Dio
  • cookies存储使用的是:dio_cookie_manager
    注意:由于在使用cookie_manager时如果采用的是持久化存储,就需要在本地一个目录保存cookies信息,但是如果只按照网上的方法,就是
dio.interceptors.add(CookieManager(PersistCookieJar(dir: "/cookies")));

这样来的话,在不同的平台上会有错误,错误信息就是,权限的问题,所以我猜测是填写的dir地址,在新建文件夹的时候没有权限,所以另外还需要使用一个库path_provider然后使用如下方式获取一个临时目录,就不会出现权限问题了

Directory tempDir = await getTemporaryDirectory();
    cookiePath = tempDir.path;

再贴上ymal需要添加的依赖

dependencies:
  #  网络请求
  dio: ^3.0.0
  dio_cookie_manager: 1.0.0
  path_provider: ^1.3.0

网络请求讲解结束

状态管理开始

状态管理在项目中我使用的是provider
同时,为了保存用户的信息,和当前状态的信息,新建了三个model信息(userinfo,mytheme,profile),
也是通过json转model的方式来实现的,因为后面还需要将model保存到本地,采用了shared_preferences,需要将model转成json存到本地
userinfo.json

{
  "username":"",
  "pwd":"",
  "islogin":false
}

mytheme.json(这里只设置了app的主题颜色)

{
  "themecolor":0
}

profile.json

{
  "userinfo":"$userinfo",
  "theme":"$mytheme"

}

运行:

flutter packages pub run json_model

生成model成功之后,我们添加需要使用到依赖

dependencies:
  #  数据管理层
  provider: 3.0.0+1

dev_dependencies:
  shared_preferences: ^0.5.3

在common下新建一个store.dart文件

import 'dart:io';

import 'package:path_provider/path_provider.dart';
import 'package:flutter/material.dart';
import 'package:wanandroid_client_app/models/index.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';



class Store{

  static String cookiePath;

  static Profile profile;
  static ColorSwatch themeColor;
  static SharedPreferences sharedPreferences;

  static dynamic init({context,child}) async{
//    初始化获取本地数据
    sharedPreferences = await SharedPreferences.getInstance();
//    获取cookie保存的目录
    Directory tempDir = await getTemporaryDirectory();
    cookiePath = tempDir.path;
    print(cookiePath);
// 通过sharedPreferences获取本地app配置
    if(sharedPreferences.get("profile")==null){
//      说明本地没有配置,一般是第一次进入app,我们就新建配置信息
      profile  = Profile();
      Userinfo userInfo = Userinfo();
//  设置用户名密码是空字符串
      userInfo.username="";
      userInfo.pwd="";
// 设置是否有用户登录为否
      userInfo.islogin = false;
      profile.userinfo = userInfo;
      Mytheme mytheme = Mytheme();
// 设置当前app的颜色默认为样式数组中的第一个
      mytheme.themecolor = themeColors[0].value;
      themeColor = themeColors[0];
      profile.theme = mytheme;
// 调用save方法,保存app配置到本地
      save();
    }else{
// 如果不为空,说明我们之前保存过设置到本地,因为保存时是保存的json格式,我们需要转换为对象
      profile = Profile.fromJson(jsonDecode(sharedPreferences.get("profile")));
    }
    print("初始化数据为");
    print(jsonDecode(sharedPreferences.get("profile")));
//    根据themecolor判断当前是哪一个color
    for(int i=0;i<themeColors.length;i++){
      if(themeColors[i].value==profile.theme.themecolor){
        themeColor = themeColors[i];
        break;
      }
    }
  }

  //保存数据到本地,将配置对象转成json保存
  static save(){
    sharedPreferences.setString("profile", jsonEncode(profile.toJson()));
  }
}


// 创建一个配置文件管理通知类
class ProfileNotifier with ChangeNotifier{
  Profile get profile => Store.profile;

  @override
  void notifyListeners() {
// 调用save方法,将新的配置信息保存到本地
    Store.save();
    super.notifyListeners();
  }
}

// 用户信息管理通知类
class UserInfoNotifier extends ProfileNotifier{
  Userinfo get userinfo => profile.userinfo;

// 设置用户信息,比如退出登录或者登陆时
  set setUserinfo(newuserinfo){
    profile.userinfo = newuserinfo;
    notifyListeners();
  }


}

// 主题颜色配置表
const List<ColorSwatch> themeColors = [
  Colors.blue,
  Colors.deepOrange,
  Colors.green,
  Colors.purple,
  Colors.pink,
  Colors.amber

];

// 主体颜色修改通知类
class ThemeNotifier extends ProfileNotifier{
  ColorSwatch get themecolor =>Store.themeColor;

  set setThemeColor(ColorSwatch newcolor){
    Store.themeColor = newcolor;
    profile.theme.themecolor = Store.themeColor.value;
    notifyListeners();
  }
}

网络请求文件创建

  • 在service目录下新建net.dart
import 'package:dio/dio.dart';
import 'package:wanandroid_client_app/models/index.dart';
import 'dart:math';
import 'package:wanandroid_client_app/common/static_info.dart';
import 'package:wanandroid_client_app/common/store.dart';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';

const String login = "user/login";
const String register = "user/register";
const String logout = "user/logout/json";
const String banner = "banner/json";
const String tree = "tree/json";
const String nav = "navi/json";
const String projectfl = "project/tree/json";
const String projectList = "project/list/PAGE/json?cid=CID";
const String tixiList = "article/list/PAGE/json?cid=CID";
const String gzh = "wxarticle/chapters/json";
const String gzhList = "wxarticle/list/CID/PAGE/json";
const String collectList = "lg/collect/list/PAGE/json";
String article = "article/list/pageIndex/json";
String collect = "lg/collect/Index/json";
String uncollect = "lg/uncollect_originId/Index/json";



//获取请求对象
Dio getDio() {
  BaseOptions baseOptions = BaseOptions(
    baseUrl: "https://www.wanandroid.com/",
  );
  Dio dio = Dio(baseOptions);
//  添加cookie管理
//  if(Store.profile.userinfo.islogin){
//
//  }
  dio.interceptors.add(CookieManager(PersistCookieJar(dir: Store.cookiePath)));
  dio.interceptors.add(LogInterceptor(responseBody: false)); //开启请求日志
  return dio;
}
//用户登录
dynamic mylogin(String username, String pwd) async {
  Map<String, String> queryParameters = {"username": username, "password": pwd};
  Dio dio = getDio();
  Response response = await dio.post(login, queryParameters: queryParameters);
  Map<String, dynamic> res = response.data;
  return BaseResponse.fromJson(res);
}
//获取首页banner
Future<List<Banner>> getBanner() async {
  Dio dio = getDio();
  Response response = await dio.get(banner);
  Map<String, dynamic> res = response.data;
  BaseListResponse baseListResponse = BaseListResponse.fromJson(res);
  List<Banner> banners = List<Banner>();
  if (baseListResponse.errorCode == 0) {
//    说明获取数据没有错误
    for (int i = 0; i < baseListResponse.data.length; i++) {
      banners.add(Banner.fromJson(baseListResponse.data[i]));
    }
  }
  return  banners;
}

//获取首页文章
Future<Page> getArticle(int index)async{

  Dio dio = getDio();
  String newarticle = article.replaceAll("pageIndex", index.toString());
  Response response = await dio.get(newarticle);
  Map<String, dynamic> res = response.data;
  BaseResponse baseListResponse = BaseResponse.fromJson(res);
  Page page = Page.fromJson(baseListResponse.data);
  for(int i=0;i<page.datas.length;i++){
    page.datas[i].shareUser = Random().nextInt(2)==1?StaticInfo.manIcon.replaceAll("Index", Random().nextInt(50).toString()):StaticInfo.womanIcon.replaceAll("Index", Random().nextInt(50).toString());
  }
  return page;
}

//收藏文章
Future<int> collectArticle(int index)async{
  Dio dio = getDio();
  String collectUrl = collect.replaceAll("Index", index.toString());
  Response response =  await dio.post(collectUrl);
  Map<String, dynamic> res = response.data;
  BaseResponse baseResponse = BaseResponse.fromJson(res);
  return baseResponse.errorCode;

}


//取消收藏文章
Future<int> unCollectArticle(int index)async{
  Dio dio = getDio();
  String uncollectUrl = uncollect.replaceAll("Index", index.toString());
  Response response =  await dio.post(uncollectUrl);
  Map<String, dynamic> res = response.data;
  BaseResponse baseResponse = BaseResponse.fromJson(res);
  return baseResponse.errorCode;

}

////获取体系分类
Future<List<Txouter>> getTreeJson()async{
  List<Txouter> txouter = List<Txouter>();
  Dio dio = getDio();
  Response response = await dio.get(tree);
  Map<String, dynamic> res = response.data;
  TreeResponse treeResponse = TreeResponse.fromJson(res);
  if(treeResponse.errorCode==0){
    txouter = treeResponse.data;
  }
  return txouter;
}

//获取导航数据
Future<List<Navouter>> getNavJson() async{
  List<Navouter> navouters = List<Navouter>();
  Dio dio = getDio();
  Response response = await dio.get(nav);
  Map<String, dynamic> res = response.data;
  NavResponse navResponse = NavResponse.fromJson(res);
  if(navResponse.errorCode==0){
    navouters = navResponse.data;
  }
  return navouters;
}

//获取项目的分类
Future<List<Projectfl>> getProjectFl() async{
  List<Projectfl> projectfls = List<Projectfl>();
  Dio dio = getDio();
  Response response = await dio.get(projectfl);
  Map<String, dynamic> res = response.data;
  ProjectReponse projectReponse = ProjectReponse.fromJson(res);
  if(projectReponse.errorCode==0){
    projectfls = projectReponse.data;
  }
  return projectfls;
}

//获取项目列表数据
Future<List<ProjectAllOuterChild>> getProjectList(int page,int cid) async{
  List<ProjectAllOuterChild> projectAllOuterChild = List<ProjectAllOuterChild>();
  ProjectAllOuter projectAllOuter;
  Dio dio = getDio();
  Response response = await dio.get(projectList.replaceAll("PAGE", page.toString()).replaceAll("CID", cid.toString()));
  Map<String, dynamic> res = response.data;
  ProjectAllResponse projectAllResponse = ProjectAllResponse.fromJson(res);
  if(projectAllResponse.errorCode==0){
    projectAllOuter = projectAllResponse.data;
    projectAllOuterChild = projectAllOuter.datas;
  }
  return projectAllOuterChild;
}



//获取体系列表数据
Future<List<ProjectAllOuterChild>> getTixiList(int page,int cid) async{
  List<ProjectAllOuterChild> projectAllOuterChild = List<ProjectAllOuterChild>();
  ProjectAllOuter projectAllOuter;
  Dio dio = getDio();
  Response response = await dio.get(tixiList.replaceAll("PAGE", page.toString()).replaceAll("CID", cid.toString()));
  Map<String, dynamic> res = response.data;
  ProjectAllResponse projectAllResponse = ProjectAllResponse.fromJson(res);
  if(projectAllResponse.errorCode==0){
    projectAllOuter = projectAllResponse.data;
    projectAllOuterChild = projectAllOuter.datas;
  }
  return projectAllOuterChild;
}

//获取公众号信息
Future<List<GzhChild>> getGzh() async{
  List<GzhChild> gzhChild = List<GzhChild>();
  Dio dio = getDio();
  Response response = await dio.get(gzh);
  Map<String, dynamic> res = response.data;
  GzhResponse gzhResponse = GzhResponse.fromJson(res);
  if(gzhResponse.errorCode==0){
    gzhChild = gzhResponse.data;
  }
  return gzhChild;
}


//获取公众号文章数据
Future<List<ProjectAllOuterChild>> getGzhList(int page,int cid) async{
  List<ProjectAllOuterChild> projectAllOuterChild = List<ProjectAllOuterChild>();
  ProjectAllOuter projectAllOuter;
  Dio dio = getDio();
  Response response = await dio.get(gzhList.replaceAll("PAGE", page.toString()).replaceAll("CID", cid.toString()));
  Map<String, dynamic> res = response.data;
  ProjectAllResponse projectAllResponse = ProjectAllResponse.fromJson(res);
  if(projectAllResponse.errorCode==0){
    projectAllOuter = projectAllResponse.data;
    projectAllOuterChild = projectAllOuter.datas;
  }
  return projectAllOuterChild;
}

//查看我的收藏列表
Future<MyCollect> getCollectList(int page) async{
  Dio dio = getDio();
  Response response = await dio.get(collectList.replaceAll("PAGE", page.toString()));
  Map<String,dynamic> res = response.data;
  MyCollectReponse myCollectReponse = MyCollectReponse.fromJson(res);
  if(myCollectReponse.errorCode==0){
    return myCollectReponse.data;
  }
  return null;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349