如何使用Flutter使用BloC访问登录时获得的身份验证令牌

问题描述

我已经完成了以下教程https://dev.to/amartyadev/flutter-app-authentication-with-django-backend-1-21cp,尽管该教程很有用,但使我仍然毫无头绪。我能够登录,并且用户详细信息通过UserRepository类(包括身份验证令牌)通过UserRepository类保存到本地的sqlite数据库中,但是当尝试向服务器重复请求数据时,我不知道如何访问它。现有代码没有任何问题,但是我将展示几页,以便您可以看到我已经做过并且正在努力实现的目标以及如何将它们组合在一起。

main.dart:

import 'package:Flutter/material.dart';
import 'package:Flutter/widgets.dart';
import 'package:bloc/bloc.dart';
import 'package:Flutter_bloc/Flutter_bloc.dart';
import './repository/user_repository.dart';

import './bloc/authentication/authentication_bloc.dart';
import './screens/splash_screen.dart';
import './screens/login/login_screen.dart';
import './screens/home_screen.dart';
import './widgets/loading_indicator.dart';
import './widgets/video_widget.dart';
import './screens/home_screen.dart';

const welcomeUrl = 'https://soundjudgement.github.io/static-sf/tour.mp4';
class SimpleBlocDelegate extends BlocDelegate {
  @override
  void onEvent(Bloc bloc,Object event) {
    super.onEvent(bloc,event);
    print(event);
  }

  @override
  void onTransition(Bloc bloc,Transition transition) {
    super.onTransition(bloc,transition);
    print(transition);
  }

  @override
  void onError(Bloc bloc,Object error,StackTrace stacktrace) {
    super.onError(bloc,error,stacktrace);
  }
}

void main() {
  BlocSupervisor.delegate = SimpleBlocDelegate();
  final userRepository = UserRepository();

  runApp(BlocProvider<AuthenticationBloc>(
    create: (context) {
      return AuthenticationBloc(userRepository: userRepository)
        ..add(AppStarted());
    },child: SundayFundayApp(userRepository: userRepository),));
}

class SundayFundayApp extends StatelessWidget {
  // This widget is the root of your application.

  final UserRepository userRepository;

  SundayFundayApp({Key key,@required this.userRepository}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'The Yard Mobile App',theme: ThemeData(
        primarySwatch: Colors.yellow,visualDensity: VisualDensity.adaptivePlatformDensity,),home: BlocBuilder<AuthenticationBloc,AuthenticationState>(
        builder: (context,state) {
          if (state is AuthenticationUnintialized) {
            return SplashPage();
          }
          if (state is AuthenticationAuthenticated) {
            return HomeScreen();
          }
          if (state is AuthenticationUnauthenticated) {
            return LogInScreen(
              userRepository: userRepository,);
          }
          if (state is AuthenticationLoading) {
            return LoadingIndicator();
          }
        },);
  }
}

user_repository.dart

import 'dart:async';
import '../models/user_model.dart';
import 'package:Meta/Meta.dart';
import '../models/api_model.dart';
import '../api_connection/api_connection.dart';
import '../dba/user_dba.dart';

class UserRepository {
  final userDao = UserDba();

  Future<User> authenticate({
    @required String username,@required String password,}) async {
    UserLogin userLogin = UserLogin(username: username,password: password);
    Token token = await getToken(userLogin);
    User user = User(
      id: 0,username: username,token: token.token,);
    return user;
  }

  Future<void> persistToken({@required User user}) async {
    // write token with the user to the database
    await userDao.createuser(user);
  }

  Future<void> deletetoken({@required int id}) async {
    await userDao.deleteUser(id);
  }

  Future<bool> hasToken() async {
    bool result = await userDao.checkUser(0);
    return result;
  }
}

user_dao.dart:

import '../database/user_database.dart';
import '../models/user_model.dart';

class UserDao {
  final dbProvider = DatabaseProvider.dbProvider;

  Future<int> createuser(User user) async {
    final db = await dbProvider.database;

    var result = db.insert(userTable,user.toDatabaseJson());
    return result;
  }

  Future<int> deleteUser(int id) async {
    final db = await dbProvider.database;
    var result = await db
        .delete(userTable,where: "id = ?",whereArgs: [id]);
    return result;
  }

  Future<bool> checkUser(int id) async {
    final db = await dbProvider.database;
    try {
      List<Map> users = await db
          .query(userTable,where: 'id = ?',whereArgs: [id]);
      if (users.length > 0) {
        return true;
      } else {
        return false;
      }
    } catch (error) {
      return false;
    }
  }
}

login_screen.dart:

import 'package:Flutter/material.dart';
import 'package:font_awesome_Flutter/font_awesome_Flutter.dart';
import '../../repository/user_repository.dart';
import 'package:Flutter_bloc/Flutter_bloc.dart';
import '../../bloc/authentication/authentication_bloc.dart';
import './bloc/login_bloc.dart';
import 'login_form.dart';

class LogInScreen extends StatelessWidget {

  final UserRepository userRepository;

  LogInScreen({Key key,@required this.userRepository})
      : assert(userRepository != null),super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method,and use it to set our appbar title.
        title: Text('The Yard App'),body:  Container(
        decoration: Boxdecoration(
          image: decorationImage(
            image: Assetimage('assets/images/theyardbook.png'),fit: BoxFit.cover,)
        ),child: BlocProvider(
          create: (context) {
            return LoginBloc(
              authenticationBloc: BlocProvider.of<AuthenticationBloc>(context),userRepository: userRepository,);
          },child: Container(
           child: Scaffold(
            backgroundColor: Colors.transparent,body: Container(
              width: MediaQuery.of(context).size.width,decoration: Boxdecoration(
                borderRadius: BorderRadius.circular(20),color: Colors.transparent,child: Padding(
                padding: EdgeInsets.all(23),child:     LoginForm(),);
  }
}

用户登录后,应用程序会将您带到主屏幕,在这个屏幕上,我放置了一个按钮,将我带到另一个屏幕,该屏幕将从服务器获取数据以进行显示。现在唯一可用的数据是一个注册用户,这很好,我只需要查看它的工作原理,因为我完全被卡住了,已经呆了3天了。我需要知道的是如何访问身份验证令牌?我假设(希望)访问保存到本地数据库的任何数据的过程都是相同的。

TIA

我可以复制并粘贴更多代码,但是我觉得那里有很多东西,而且教程非常清楚,它可以帮助我完成最后的工作

解决方法

因此,这是user-dao中的代码,我只需要将其导入需要访问服务器的任何小部件/类中即可。似乎很明显,而且很直截了当,但是在我不熟悉的所有Dart代码以及bloc模式中使用的许多文件中,我认为我的想法变得困惑了。

  Future<String> getUserToken(int id) async {
    final db = await dbProvider.database;
    try {
      var res = await db.rawQuery("SELECT token FROM userTable WHERE id=0");
      return res.isNotEmpty ? (User.fromDatabaseJson(res.first)).token : null;
    } catch (err) {
      return null;
    }
  }

这是使用FutureBuilder的新用户屏幕代码

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../widgets/logout_button.dart';
import '../repository/user_repository.dart';
import 'package:http/http.dart' as http;
import '../dao/user_dao.dart';
import '../api_connection/api_connection.dart';
import '../models/user_model.dart';

class UserScreen extends StatefulWidget {

  @override
  _UserScreenState createState() => _UserScreenState();
}

class _UserScreenState extends State<UserScreen> {

  Future<User> futureUser;

  @override
  void initState() {
    super.initState();
    futureUser = getUser();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('The Yard Users'),),body: Container(
        child: FutureBuilder( // use a future builder widget
          future: futureUser,// assign the future
          builder: (context,snapshot) {
            if (snapshot.hasData) {
              return Column(
                // show your layout if future is done
                mainAxisAlignment: MainAxisAlignment.center,crossAxisAlignment: CrossAxisAlignment.center,children: <Widget>[
                  Padding(
                    padding: EdgeInsets.only(left: 30.0),child: Text(
                      'Username: ${snapshot.data.username}',// get the username from the snapshot
                      style: TextStyle(
                        fontSize: 24.0,// Logout button
                  Padding(
                    padding: EdgeInsets.fromLTRB(34.0,20.0,0.0,0.0),child: Container(
                        width: MediaQuery.of(context).size.width * 0.85,height: MediaQuery.of(context).size.width * 0.16,child: LogoutButton()
                    ),],);
            } else {
              return CircularProgressIndicator(); // show a progress indicator while future is executing
            }
          },);
  }
}