Flutter開始干係列-一個完整的登陸實踐

直接開始幹,沒有爲何~android


基於上一篇實現一個登錄頁,使用 connectivityshared_preferencesDio 實現一個完整的登陸操做,包含網絡鏈接檢測、請求、數據存儲等~git

固然,登陸接口並非我實現,是由玩Android友情提供。首先看效果:github

效果圖

插件簡介

connectivity

用於發現網絡鏈接並進行相應配置。它能夠區分蜂窩鏈接和WiFi鏈接,iOS和Android適用。json

注意 在Android上,這不保證能夠鏈接到Internet網絡

shared_preferences

包裝NSUserDefaults(在iOS上)和SharedPreferences(在Android上),爲簡單數據提供持久存儲。app

Dio

dio是一個強大的Dart Http請求庫,支持Restful API、FormData、攔截器、請求取消、Cookie管理、文件上傳/下載、超時、自定義適配器等。async

依賴配置

在 pubspec.yaml 中添加插件依賴,下面插件版本是文章編寫時的最新版。ide

dependencies:
  # https://github.com/flutterchina/dio
  dio: ^3.0.3
  
  # https://github.com/flutter/plugins/tree/master/packages/connectivity
  connectivity: ^0.4.4
  
  # https://github.com/flutter/plugins/tree/master/packages/shared_preferences
  shared_preferences: ^0.5.3+4
複製代碼

登陸操做

今天的全部操做都基於上一篇實現一個登錄頁,有必要的能夠先跳轉過去查看。post

使用 Dio 構建登陸請求

登陸按鈕的 onPressed 回調中,替換爲 _doLogin() ,實現以下:spa

Future _doLogin() async {
    Dio dio = Dio();

    dio.options..baseUrl = 'https://www.wanandroid.com/';

    // 添加攔截器
    dio.interceptors
      ..add(LogInterceptor(
        requestHeader: true,
        requestBody: true,
        responseHeader: true,
        responseBody: true,
      ));

    // 發起請求
    Response response = await dio.post('user/login',
        data: FormData.fromMap({
          "username": _accountController.text.trim(),
          "password": _pwdController.text.trim(),
        }));

    if (response.statusCode == 200) {
      UserEntity user = UserEntity.fromJson(response.data);
      if (user.errorCode == 0) {
        _showInfoDialog('登陸成功');
      } else {
        _showInfoDialog('登陸失敗:${user.errorMsg}');
      }
    } else {
      _showInfoDialog('網絡請求異常:${response.statusMessage}');
    }
  }
複製代碼

點擊登陸,帳號密碼正確的狀況下,你將看到登陸成功!

登陸成功效果圖

發起請求前檢測網絡

在發起網絡請求前,咱們通常會檢測網絡,有網絡就發起,沒網絡就算逑... 須要注意這個庫在 Android 上還有個注意事項。

所在在 post 發起以前加上以下代碼,校驗網絡鏈接檢測:

// 檢測網絡鏈接
    var connectivityResult = await (Connectivity().checkConnectivity());
    if (connectivityResult == ConnectivityResult.none) {
      _showInfoDialog('網絡鏈接異常');
      return;
    }
複製代碼

存儲登陸結果

通常登陸成功後,咱們會保存用戶信息,以便在後續操做使用到時方便獲取。

因此在確認真正登陸成功後,添加以下代碼保存用戶信息:

//登陸成功後 保存信息
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString('user', jsonEncode(user.data));
複製代碼

connectivity 、shared_preferences 插件使用相對簡單,就再也不廢話了。到這一步若是網絡鏈接正常,且帳號密碼正確,將看到上面第一張圖示效果。不然:

網絡鏈接異常

攔截器添加請求頭

登陸成功後,接下來須要在全部的請求中加上 token ,固然可能還有一些硬件信息什麼的。這裏經過添加 Dio 攔截器實現:

// 添加攔截器
    dio.interceptors
      ..add(InterceptorsWrapper(
        onRequest: (RequestOptions options) async {
          var prefs = await SharedPreferences.getInstance();
          var userJson = prefs.getString('user');
          if (userJson != null && userJson.isNotEmpty) {
            UserData user = UserData.fromJson(jsonDecode(userJson));
            options.headers
              ..addAll({
                'userId': user.id ?? '',
                'token': user.token ?? '',
              });
          }
          return options;
        },
      ))
複製代碼

這樣網絡請求就會被攔截,添加 userId 和 token ...

請求提示

通常進行網絡請求或者耗時操做時,會給用戶一個友好的提示,表示咱們沒有卡死。我這裏的處理是封裝了一個 LoadingDialog 的 Widget,使用 showDialog() 彈出,效果以下,具體實現請看代碼。

加載效果

結尾

這個登陸實踐比較簡單,沒有對請求作統一的封裝,也沒有對異常進行處理。通常都是封裝後統一處理,調用的地方簡單不少。

最終 _doLogin 方法中的所有代碼,

Future _doLogin() async {
    Dio dio = Dio();

    dio.options..baseUrl = 'https://www.wanandroid.com/';

    // 添加攔截器
    dio.interceptors
      ..add(InterceptorsWrapper(
        onRequest: (RequestOptions options) async {
          var prefs = await SharedPreferences.getInstance();
          var userJson = prefs.getString('user');
          if (userJson != null && userJson.isNotEmpty) {
            UserData user = UserData.fromJson(jsonDecode(userJson));
            options.headers
              ..addAll({
                'userId': user.id ?? '',
                'token': user.token ?? '',
              });
          }
          return options;
        },
      ))
      ..add(LogInterceptor(
        requestHeader: true,
        requestBody: true,
        responseHeader: true,
        responseBody: true,
      ));

    // 檢測網絡鏈接
    var connectivityResult = await (Connectivity().checkConnectivity());
    if (connectivityResult == ConnectivityResult.none) {
      _showInfoDialog('網絡鏈接異常');
      return;
    }

    LoadingDialog.show(context);

    // 發起請求
    Response response = await dio.post('user/login',
        data: FormData.fromMap({
          "username": _accountController.text.trim(),
          "password": _pwdController.text.trim(),
        }));

    if (response.statusCode == 200) {
      UserEntity user = UserEntity.fromJson(response.data);
      if (user.errorCode == 0) {
        //登陸成功後 保存信息
        SharedPreferences prefs = await SharedPreferences.getInstance();
        prefs.setString('user', jsonEncode(user.data));
        _showInfoDialog('登陸成功');
      } else {
        _showInfoDialog('登陸失敗:${user.errorMsg}');
      }
    } else {
      _showInfoDialog('網絡請求異常:${response.statusMessage}');
    }
    LoadingDialog.hide(context);
  }
複製代碼

最後附上Github地址github.com/joker-fu/fl…

相關文章
相關標籤/搜索