如何使用 dio 在 flutter 中成功响应时导航到不同的屏幕

How to navigate to different screen on success response in flutter using dio

我正在尝试使用 dio 在成功响应后导航到其他屏幕。但是我有一个错误,并且在登录时仍然堆栈。

我还在用 flutter 入门。

这是我的登录页面

import 'dart:ui';
import 'package:app/utils/api_provider.dart';
import 'package:flutter_signin_button/button_list.dart';
import 'package:flutter_signin_button/button_view.dart';
import 'package:app/utils/Strings.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:app/screens/signupscreen.dart';

import 'home_screen.dart';

class Loginscreen extends StatefulWidget {
  @override
  _LoginscreenState createState() => _LoginscreenState();
}

class _LoginscreenState extends State<Loginscreen> {
  String loginUrl = Africapital.login_url;
  String msgError = "";

  TextEditingController _usernameee = new TextEditingController();
  TextEditingController _password = new TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: SingleChildScrollView(
        child: Container(
          decoration: BoxDecoration(
            gradient: LinearGradient(
                colors: [Colors.white, Colors.white],
                begin: Alignment.bottomLeft,
                end: Alignment.topLeft),
          ),
          child: Center(
            child: Column(
              children: <Widget>[
                SizedBox(
                  height: 50,
                ),
                new Container(
                  alignment: Alignment.center,
                  height: 100,
                  width: 100,
                  margin: EdgeInsets.only(
                    left: 40.0,
                  ),
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(100),
                    color: Colors.white60,
                    boxShadow: [
                      BoxShadow(color: Colors.white60, spreadRadius: 5),
                    ],
                    image: DecorationImage(
                      image: AssetImage('assets/images/44.jpg'),
                      fit: BoxFit.contain,
                    ),
                  ),
                ),
                SizedBox(
                  height: 15,
                ),
                Center(
                  child: Text(msgError,
                      style: TextStyle(
                          color: Colors.red,
                          fontWeight: FontWeight.bold,
                          fontSize: 20)),
                ),
                SizedBox(
                  height: 5,
                ),
                Container(
                  alignment: Alignment(-0.90, 0.90),
                  margin: const EdgeInsets.only(left: 20.0, right: 20.0),
                  child: Text(
                    'Sign in with your account',
                    style: TextStyle(
                        color: Colors.black54,
                        fontSize: 16,
                        fontWeight: FontWeight.w500),
                  ),
                ),
                SizedBox(
                  height: 20.0,
                ),
                Container(
                  alignment: Alignment.center,
                  margin: const EdgeInsets.only(left: 20.0, right: 20.0),
                  padding: const EdgeInsets.only(left: 1, right: 1),
                  child: TextField(
                    controller: _usernameee,
                    cursorColor: Colors.indigoAccent,
                    style: TextStyle(color: Color(0xFF1a60be)),
                    decoration: new InputDecoration(
                      contentPadding: const EdgeInsets.symmetric(vertical: 5.0),
                      labelText: '      Email',
                      focusedBorder: OutlineInputBorder(
                        borderSide:
                            BorderSide(color: Color(0xFF1a60be), width: 2.0),
                      ),
                      enabledBorder: OutlineInputBorder(
                        borderSide:
                            BorderSide(color: Colors.black38, width: 1.0),
                      ),
                      hintText: '      email@email.com',
                      hintStyle: TextStyle(
                          fontSize: 15,
                          letterSpacing: 1.5,
                          color: Color(0xFF1a60be),
                          fontWeight: FontWeight.w900),
                      filled: true,
                      hoverColor: Colors.black,
                      focusColor: Colors.transparent,
                      fillColor: Colors.white.withOpacity(0.3),
                      border: OutlineInputBorder(
                        borderSide: BorderSide(color: Colors.white38),
                        borderRadius: BorderRadius.circular(10),
                      ),
                    ),
                  ),
                ),
                SizedBox(
                  height: 20,
                ),
                Container(
                  alignment: Alignment.center,
                  margin: const EdgeInsets.only(left: 20.0, right: 20.0),
                  padding: const EdgeInsets.only(left: 1, right: 1),
                  child: TextField(
                    controller: _password,
                    obscureText: true,
                    cursorColor: Colors.indigoAccent,
                    style: TextStyle(color: Color(0xFF1a60be)),
                    decoration: new InputDecoration(
                      labelText: '      Password',
                      contentPadding: const EdgeInsets.symmetric(vertical: 5.0),
                      focusedBorder: OutlineInputBorder(
                        borderSide:
                            BorderSide(color: Color(0xFF1a60be), width: 2.0),
                      ),
                      enabledBorder: OutlineInputBorder(
                        borderSide:
                            BorderSide(color: Colors.black38, width: 1.0),
                      ),
                      hintText: '    ••••••••',
                      hintStyle: TextStyle(
                          fontSize: 25,
                          letterSpacing: 2.5,
                          color: Color(0xFF1a60be),
                          fontWeight: FontWeight.w900),
                      filled: true,
                      hoverColor: Colors.black,
                      focusColor: Colors.transparent,
                      fillColor: Colors.white.withOpacity(0.3),
                      border: OutlineInputBorder(
                        borderSide: BorderSide(color: Colors.white38),
                        borderRadius: BorderRadius.circular(10),
                      ),
                    ),
                  ),
                ),
                SizedBox(
                  height: 20,
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.end,
                  children: <Widget>[
                    GestureDetector(
                      onTap: () {},
                      child: Container(
                        child: Text(
                          'Forgot Password?',
                          style: TextStyle(
                              color: Colors.black, fontWeight: FontWeight.w700),
                        ),
                      ),
                    ),
                    SizedBox(
                      width: 40,
                    )
                  ],
                ),
                SizedBox(
                  height: 20,
                ),
                Padding(
                  padding: const EdgeInsets.only(left: 25, right: 25),
                  child: ButtonTheme(
                      buttonColor: Color(0xFF3fc99c),
                      minWidth: MediaQuery.of(context).size.width,
                      height: 45,
                      child: RaisedButton(
                        onPressed: () {
                          _doLogin(context);
                        },
                        child: Text(
                          'Continue',
                          style: TextStyle(color: Colors.white, fontSize: 22),
                        ),
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(5)),
                      )),
                ),
                SizedBox(
                  height: 20,
                ),
                Align(
                  alignment: Alignment(-0.80, 0.90),
                  child: Text(
                    'Or Continue with',
                    style: TextStyle(
                        color: Colors.black54,
                        fontSize: 16,
                        fontWeight: FontWeight.w800),
                  ),
                ),
                SizedBox(
                  height: 20,
                ),
                Container(
                  width: MediaQuery.of(context).size.width,
                  height: 45,
                  margin: const EdgeInsets.only(left: 25, right: 25),
                  child: SignInButton(
                    Buttons.Google,
                    onPressed: () {},
                  ),
                ),
                SizedBox(
                  height: 20,
                ),
                Container(
                  width: MediaQuery.of(context).size.width,
                  height: 45,
                  margin: const EdgeInsets.only(left: 25, right: 25),
                  child: SignInButton(
                    Buttons.Facebook,
                    onPressed: () {},
                  ),
                ),
                SizedBox(
                  height: 25,
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Text(
                      "Don't Have an Account?",
                      style: TextStyle(
                          color: Colors.black87,
                          fontSize: 14,
                          fontWeight: FontWeight.w400),
                    ),
                    SizedBox(
                      width: 10,
                    ),
                    GestureDetector(
                      onTap: () {
                        Navigator.push(context,
                            MaterialPageRoute(builder: (ctx) => Signscreen()));
                      },
                      child: Text(
                        'Sign up',
                        style: TextStyle(
                          decoration: TextDecoration.underline,
                          fontWeight: FontWeight.w800,
                          fontSize: 18,
                          color: Colors.black,
                        ),
                      ),
                    ),
                    SizedBox(
                      height: 40,
                    ),
                  ],
                )
              ],
            ),
          ),
        ),
      ),
    );
  }

  void _doLogin(BuildContext context) async {
    String usernameee = _usernameee.text;
    String password = _password.text;
    ApiProvider apiService = new ApiProvider();
    print("hello");
    final loginresponse =
        await apiService.getLogin(uname: usernameee, passcode: password);
    if (loginresponse.response.data != 200) {
      throw Exception("error");
    } else {
      navigateToSubPage(context);
    }
  }

  Future navigateToSubPage(context) async {
    Navigator.push(
        context, MaterialPageRoute(builder: (context) => HomeScreen()));
  }
}

这是我的 api_provider.dart

import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter_session/flutter_session.dart';

class ApiProvider {
  Dio _dio;
  String aToken = '';

  final BaseOptions options = new BaseOptions(
    baseUrl: 'https://sooo.co.ke/africanapp/',
    connectTimeout: 15000,
    receiveTimeout: 13000,
  );
  static final ApiProvider _instance = ApiProvider._internal();

  factory ApiProvider() => _instance;

  ApiProvider._internal() {
    _dio = Dio(options);
    _dio.interceptors
        .add(InterceptorsWrapper(onRequest: (Options options) async {
      // to prevent other request enter this interceptor.
      _dio.interceptors.requestLock.lock();
      // We use a new Dio(to avoid dead lock) instance to request token.
      //Set the cookie to headers
      options.headers["cookie"] = aToken;

      _dio.interceptors.requestLock.unlock();
      return options; //continue
    }));
  }

  // ignore: missing_return
  Future<LoginApiResponse> getLogin({String passcode, String uname}) async {
    final request = {"email": uname, "password": passcode};

    FormData formData = FormData.fromMap({
      'email': uname,
      'password': passcode,
    });

    print(request);

    try {
      final response = await _dio.post('/', data: formData);
      //getting cookies from response
      String jsonsDataString = response.data.toString();
      final jsonData = jsonDecode(jsonsDataString);

      final cookies = response.headers.map['set-cookie'];
      print(cookies);
      print(response.data);
      var message = jsonData['msg'];
      var usrid = jsonData['uid'];
      var name = jsonData['username'];
      var mail = jsonData['email'];
      var images = jsonData['profile'];

      if (message == "welcomeback") {
        await FlutterSession().set('username', usrid);
        await FlutterSession().set('username', name);
        await FlutterSession().set('email', mail);
        await FlutterSession().set('image', images);
        print(message + " dan status : " + message);
      }

      //print(response.headers.toString());
      if (response.statusCode == 200) {
        final authToken = cookies[1].split(';')[0]; // server sending cookie
        // authToken in local storage, pass5. in further api calls.
        aToken =
            authToken; // global variable to refresh current api calls to add cookie.
        print(authToken);
      } else {
        // If that response was not OK, throw an error.
        throw Exception('Failed to load post');
      }
      return LoginApiResponse(jsonData);
    } catch (e) {
      print('Error: $e');
    }

    
  }

}

class LoginApiResponse {
  final Response response;
  LoginApiResponse(this.response);
}

任何人都可以检查一下并告诉我我的问题出在哪里。提前谢谢你。

我真的很需要这个帮助,我迫不及待地想尽快完成我的项目。

请帮忙。

final jsonData = jsonDecode(jsonsDataString);
...
return LoginApiResponse(jsonData);
...
if (loginresponse.response.data != 200) 

解码后jsonData只有data部分没有statusCode,所以在_doLogin的loginresponse中( ) 你不会有状态部分,因此你不会导航到其他页面。

好的,我知道你想在这里实现什么。 所以基本上你想在响应成功时导航到另一个屏幕。 所以,您的情况如下:

if(response.statusCode == 200){
// rest of code here before navigation.
 Navigator.push(context, MaterialPageRoute(builder: (context) => HomeScreen));
}