flutter登陆机制

登录流程

登陆机制的流程其实很简单,简单来说就是:

  1. 通过手机号获取验证码
  2. 输入验证码,根据手机号和验证码去登陆
  3. 登陆的时候设置用户的登录状态,下次打开以后免登录

1.验证码获取

TextField(
  controller: _codeController
)

使用文本框小部件中的controller的回调函数获取文本框中的内容

getCodeBuilder() {
    _presenter.getCode(_phoneNumberController.text);
  }

调用LoginPresent类中的getCode方法根据手机号去获取验证码,如果返回的是ture,表示获取验证码成功,如果返回的是null,表示获取验证码失败。
这里的Boast.show()Boast类里面的一个静态方法,方法接收一个必选参数(显示信息)和一个可选参数(延迟时间,默认是一秒)。

getCode(String mobile) async {
    try {
      List result = await Future.wait([
        _securityCodeDatasourceApi.getSecurityCodeByMobile(mobile.trim()),
      ]);
      bool isSuccess = result[0];
      if (isSuccess == null) {
        Boast.show('验证码发送失败');
        return;
      }
      Boast.show('验证码已发送');
    } catch (e) {
      Boast.show('验证码发送失败');
    }
  }

下面这段代码就是调用API类的getSecurityCodeByMobile方法,调用接口,通过手机号去获取验证码。

 _securityCodeDatasourceApi.getSecurityCodeByMobile(mobile.trim())

getSecurityCodeByMobile方法的具体内容如下:
通过NetworkUtil类的get方法调用接口,获得数据并返回;
then里面的(dynamic res)res就是get方法得到的结果数据。

Future<bool> getSecurityCodeByMobile(String mobile) {
    return _netUtil
        .get('member', '/api/xxx/xxx?mobile=$mobile')
        .then((dynamic res) {
      if (res != null) {
        return res['isSuccess'];
      }
      return null;
    });
  }

解释一下上面的get方法

Future<dynamic> get(String b, String url) {
    if (b != null) {
      //获取biz和url将url进行拼接,biz_domains是一个配置文件
      url = b_domains[b] + url;
    }
    //getHeaders()方法完善请求头信息,然后
    return getHeaders().then((headers) {
      return http.get(url, headers: headers).then((response) {
        //响应体内容
        final String res = response.body;
        //响应的状态
        final int statusCode = response.statusCode;
        //根据状态判断该抛出什么异常
        if (statusCode < 200 || statusCode > 400 || json == null) {
          throw new Exception("Error while fetching data");
        }
        //返回一个Map<String, dynamic>类型的数据
        return json.decode(res);
      });
    });
  }

上面代码中用到的getHeaders()方法

Future<Map<String, String>> getHeaders() {
    //AuthStateProvider类其实就是一恶搞用户登录状态监听的类,
    return (new AuthStateProvider()).getLoginInfo().then((loginInfo) {
      //定义响应头的Content-Type类型是json类型
      Map<String, String> headers = {'Content-Type': 'application/json'};
      //如果登陆信息不为空,响应头部添加token信息
      if (loginInfo != null) {
        headers['Authorization'] = 'Bearer ${loginInfo.token}';
      }
      return headers;
    });
  }

2.手机、验证码验证登陆

用户输入手机号和收到的验证码,点击登陆,触发点击事件,点击事件通过LoginPresent类中的loginByMobile方法去验证登陆

//点击事件的回调函数
void _submit() {
    _presenter.loginByMobile(_phoneNumberController.text, _codeController.text);
  }
//点击按钮
RaisedButton(
  onPressed: _submit,
);

loginByMobile函数解析:

loginByMobile(String mobile, String code) async {
    AuthStateProvider provider = new AuthStateProvider();
    try {
      //通过API获取用户登录信息
      LoginInfo loginInfo = await _securityCodeDatasourceApi.loginByMobile(
          mobile.trim(), code.trim());
      //如果token为空,登陆失败
      if (loginInfo.token.isEmpty) {
        BMToast.show('网络连接失败');
        return;
      }
      //登陆成功以后设置登陆信息
      await provider.setLoginInfo(loginInfo);
      //调用api获取用户信息
      User user = await api.getUserInfo();
      //设置用户信息
      await provider.setUserInfo(user);
    } catch (e) {
      BMToast.show('网络连接失败');
    }
  }

登陆的流程其实和验证码获取的流程差不多的,多出来的一部分就是如果用户登陆成功,那么就要记住用户已经登陆过的这个状态,下次打开app的时候就不用再去登陆了。
要做到这些,就需要刚才的两步:

//登陆成功以后设置登陆信息
await provider.setLoginInfo(loginInfo);
//调用api获取用户信息
User user = await api.getUserInfo();
 //设置用户信息
await provider.setUserInfo(user);

这里的setLoginInfo方法是AuthStateProvider类里的一个方法,用来设置登陆信息,这里的PRES_LOGIN_INFO_KEY其实就是token的前缀,loginInfo.toJson()这里面其实就只有token,最后 this.notify(AuthState.LOGGED_IN);将用户的登录状态变成了“登陆状态”。

void setLoginInfo(LoginInfo loginInfo) async {
    this.loginInfo = loginInfo;
    await StorageUtil.set(PRES_LOGIN_INFO_KEY, loginInfo.toJson());
    this.notify(AuthState.LOGGED_IN);
  }

StorageUtil.set()方法则是存储用户登陆信息的一个类:
这个方法主要是根据data的类型类分别决定要用prefs里的哪个方法,而这个SharedPreferences类暂时没有看懂

static set(String key, data) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    if (data is int) {
      prefs.setInt(key, data);
    } else if (data is double) {
      prefs.setDouble(key, data);
    } else if (data is String) {
      prefs.setString(key, data);
    } else if (data is List<String>) {
      prefs.setStringList(key, data);
    } else if (data is bool) {
      prefs.setBool(key, data);
    } else if (data is Map) {
      prefs.setString(key, json.encode(data));
    } else {
      throw new Exception('cannt found data type');
    }
  }

最后要说的是

await provider.setUserInfo(user);

首先看provider.setUserInfo()方法

void setUserInfo(User userInfo) async {
    this.userInfo = userInfo;
    await StorageUtil.set(PRES_USER_INFO_KEY, userInfo.toJson());
  }

这个方法做的事情有

  1. 为本类中的userInfo赋值
  2. 存储用户信息,以key:value的形式。
    这里的StorageUtil虽然看不懂,但是可以根据await判断,这个数据应该是存储到了远程。同样登陆信息也是存储在了远程。

至此,登陆流程因该是走通了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,084评论 1 32
  • 一、Python简介和环境搭建以及pip的安装 4课时实验课主要内容 【Python简介】: Python 是一个...
    _小老虎_阅读 5,719评论 0 10
  • 似乎在寻找适合多年以前那时心情的言语,找到了,却不知哪个更适合。 焦虑和紧张,有什么不同呢?是前者滋生后者,还是后...
    微兰微澜阅读 335评论 0 3
  • 45
    红昔昔阅读 134评论 0 1