Django 백엔드의 flatter를 사용하여 애플리케이션 등록/로그인 #3

76361 단어 djangodartblocflutter

이 문장은 무엇에 관한 것입니까


앞의 두 문장에서 저는 DRF의 도움으로 Django로 API를 만들었습니다(본문 전에 읽으십시오: post #1, post #2.이 글은 이 API를 사용하여 실행되는 떨림 응용 프로그램을 소개합니다.사용자가 로그인하고 로그아웃할 수 있도록 프로그램을 만들 것입니다.
또한 this repo 에서 소스 코드를 볼 수 있습니다.
애플리케이션 데모:

선결 조건


본문을 읽으려면 바이브레이션 (참조: https://flutter.dev/docs/get-started/install 과 비주얼 스튜디오 코드와 바이브레이션 확장 (참조: https://flutter.dev/docs/development/tools/vs-code 과bloc (참조: https://marketplace.visualstudio.com/items?itemName=FelixAngelov.bloc 을 설치해야 합니다.

시작합시다.

  • 우선 bloc_login이라는 프로젝트를 만듭니다. (vscode 확장이 가장 좋습니다.) (Ctrl + shift + p, flatter를 입력하면 새 프로젝트를 만드는 옵션을 얻을 수 있습니다.)

  • 다음은 코드의 다른 구성 요소를 분리하기 위해 일부 폴더를 만들 것입니다.bloc\u 로그인에서 다음 디렉터리 만들기/
  • api_연결(우리의api와 통신하는 코드를 포함할 것)
  • 공통(로드 표시기 등 유틸리티 소부품 포함)
  • dao(우리의 qlite 데이터베이스와 통신할 수 있도록 도움말 파일을 포함할 것)
  • 모델(우리 데이터베이스를 포함하는 모델)
  • 저장소(API, blocs, 데이터베이스 간의 교량으로 사용)
  • 플래시(플래시 코드 포함)
  • 로그인(로그인 양식 및 관련 추가 세부 정보 포함)
  • 데이터베이스(데이터베이스를 초기화하고 테이블을 만들어 데이터 삽입을 시작할 수 있도록 파일 포함)
  • 홈 페이지(마스터 UI 포함)
  • 당신은 this 페이지를 참고하여 떨림 블록의 작업 원리를 기본적으로 이해할 수 있습니다.그룹이 실제로 무엇인지 이해하려면 this 페이지를 읽을 수 있다.요컨대, 이것은 전송된 이벤트를 진동이 소모되는 상태에 비추어 필요에 따라 UI를 재구성하는 방법이다.
  • 의존 항목을 추가합니다.equalable,flatter\ubloc,sqflite,http 패키지를 사용하여pub스펙을 수정합니다.yaml 파일은 다음과 같은 종속성을 포함합니다.
  • dependencies:
      flutter:
        sdk: flutter
      flutter_bloc: ^3.2.0
      meta: ^1.1.6
      equatable: ^1.1.0
      http: ^0.12.0+4
      sqflite: ^1.3.0
      path_provider: ^1.6.5
      # The following adds the Cupertino Icons font to your application.
      # Use with the CupertinoIcons class for iOS style icons.
      cupertino_icons: ^0.1.2
    
    주의: 의존 항목 부분을 보여 드렸습니다. 의존 항목을 추가해야 하는 파일입니다.
    파일을 VScode에 저장하면 패키지를 가져오는 명령이 자동으로 실행되지만 참조하기 쉽도록 bloc_login/ 디렉토리에서 다음 명령을 실행합니다.
    flutter pub get
    
  • 데이터베이스 도우미를 만드는 것부터 시작하여 user_database.dart 디렉터리에 파일bloc_directory/database을 만들고 다음 코드를 추가합니다.
  • import 'dart:async';
    import 'dart:io';
    
    import 'package:path/path.dart';
    import 'package:path_provider/path_provider.dart';
    import 'package:sqflite/sqflite.dart';
    
    final userTable = 'userTable';
    
    class DatabaseProvider {
      static final DatabaseProvider dbProvider = DatabaseProvider();
    
      Database _database;
    
      Future <Database> get database async {
        if (_database != null){
          return _database;
        }
        _database = await createDatabase();
        return _database;
      }
    
      createDatabase() async {
        Directory documentsDirectory = await getApplicationDocumentsDirectory();
        String path = join(documentsDirectory.path, "User.db");
    
        var database = await openDatabase(
          path,
          version: 1,
          onCreate: initDB,
          onUpgrade: onUpgrade,
        );
        return database;
      }
    
      void onUpgrade(
        Database database,
        int oldVersion,
        int newVersion,
      ){
        if (newVersion > oldVersion){}
      }
    
      void initDB(Database database, int version) async {
        await database.execute(
          "CREATE TABLE $userTable ("
          "id INTEGER PRIMARY KEY, "
          "username TEXT, "
          "token TEXT "
          ")"
        );
      }
    }
    
    여기서 열린 데이터베이스를 DatabaseProvider 클래스의 database 변수로 되돌려줍니다.따라서 dbProvider 클래스를 초기화하고 get 데이터베이스 함수를 가지고 있으며, 이 함수는 열린 데이터베이스로 되돌아옵니다.
    서로 다른 버전 간에 약간의 변경이 필요하다면, 우리는 DatabaseProvider 함수를 사용할 수 있다.마지막 onUpgrade 변수는 데이터베이스를 저장하는 데 사용되는 테이블 이름입니다.
  • 다음에 사용자를 위해 방금 만든 표에 대응하는 모델을 만듭니다.따라서 파일userTable을 만들고 다음 코드를 추가합니다.
  • class User {
      int id;
      String username;
      String token;
    
      User(
          {this.id,
          this.username,
          this.token});
    
      factory User.fromDatabaseJson(Map<String, dynamic> data) => User(
          id: data['id'],
          username: data['username'],
          token: data['token'],
      );
    
      Map<String, dynamic> toDatabaseJson() => {
            "id": this.id,
            "username": this.username,
            "token": this.token
          };
    }
    
    여기에서 우리는 공장 함수인fromDatabaseJson을 정의했다. 사용자를 JSON 대상으로 되돌려주고 toDatabaseJson은 전송된 JSON 대상을 데이터베이스에 저장할 수 있는 데이터베이스 대상으로 바꾸는 것을 책임진다.
  • API 기능을 추가하여 파일bloc_login/model/user_model.dart을 만들고 다음 코드를 추가합니다.
  • import 'dart:async';
    import 'dart:convert';
    import 'package:http/http.dart' as http;
    import 'package:bloc_login/model/api_model.dart';
    
    final _base = "https://home-hub-app.herokuapp.com";
    final _tokenEndpoint = "/api-token-auth/";
    final _tokenURL = _base + _tokenEndpoint;
    
    Future<Token> getToken(UserLogin userLogin) async {
      print(_tokenURL);
      final http.Response response = await http.post(
        _tokenURL,
        headers: <String, String>{
          'Content-Type': 'application/json; charset=UTF-8',
        },
        body: jsonEncode(userLogin.toDatabaseJson()),
      );
      if (response.statusCode == 200) {
        return Token.fromJson(json.decode(response.body));
      } else {
        print(json.decode(response.body).toString());
        throw Exception(json.decode(response.body));
      }
    }
    
    나는 위의 URL을 사용했다. 왜냐하면 나는 나의 응용 프로그램 home\uhub를 heroku라고 명명했기 때문이다. 너는 그것을 얻은 URL로 바꾸어야 한다.나머지 부분은 변하지 않을 수 있다.
    특정 사용자에게 영패를 가져오고 디테일이 정확하지 않은 상황에서 오류를 던지기 위해helper 함수만 있습니다.
  • API에 대한 요청과 후속 응답을 처리하기 위해 모델을 추가합니다.파일bloc_login/api_connection/api_connection.dart을 만들고 다음 코드를 추가합니다.
  • class UserLogin {
      String username;
      String password;
    
      UserLogin({this.username, this.password});
    
      Map <String, dynamic> toDatabaseJson() => {
        "username": this.username,
        "password": this.password
      };
    }
    
    class Token{
      String token;
    
      Token({this.token});
    
      factory Token.fromJson(Map<String, dynamic> json) {
        return Token(
          token: json['token']
        );
      }
    }
    
    사용자로부터 사용자 이름과 비밀번호를 얻고 서버에 보낼 수 있도록 이 모델을 사용할 것입니다.Token 클래스에서 결과를 가져오고 서버에서 받은 JSON 객체에서 문자열을 제공합니다.
  • 사용자 모델과 데이터베이스에 기본적인 조작을 제공하고 파일bloc_login/model/api_model.dart을 만들며 다음 코드를 추가합니다.
  • import 'package:bloc_login/database/user_database.dart';
    import 'package:bloc_login/model/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;
        }
      }
    }
    
    이것은 기본적으로 사용자를 만들거나 삭제하고 사용자의 존재 여부를 검색하는 방법을 제공합니다.우리 프로그램은 최대 한 사용자에게만 로그인 기능을 제공하기 때문에, id가 0인 사용자를 강제로 만들고 있습니다.따라서 우리는 항상 데이터베이스에 있는 첫 번째 항목을 검사함으로써 사용자가 존재하는지 확인할 수 있다.가장 좋은 것은 우리가 입력한 비밀번호가 아니라 사용자 이름과 영패를 저장하는 것이다.암호는 서버에 요청을 보내는 데 사용될 뿐, 우리는 지금까지 그 어느 곳보다 저장된 적이 없다.여기에는 영패를 항상 저장하고 사용할 수 있는 대체 방법이 있습니다. 그러나 다른 기능을 포함하기 위해 프로그램을 확장하고 싶기 때문에 SQL을 사용하고 싶습니다.
  • 응용 프로그램의 논리적 실현, 즉 집단을 살펴보자.vscode 확장을 사용하여 새로운bloc를 만드는 것을 권장합니다. (참조: flutter_secure_storage) 단, 파일을 수동으로 만들 수 있습니다.bloc_login/dao/user_dao.dart 디렉터리에 새로운bloc를 만들고 이를authentication_bloc라고 명명합니다.
    확장자는 자동으로 bloc_login. 폴더를 만들고 그 중에서 상태, 이벤트, authentication_bloc에 대응하는 세 개의 파일을 만듭니다.수정bloc_login/bloc 및 다음 코드 추가:
  • part of 'authentication_bloc.dart';
    
    abstract class AuthenticationState extends Equatable {
      @override
      List<Object> get props => [];
    }
    
    class AuthenticationUnintialized extends AuthenticationState {}
    
    class AuthenticationAuthenticated extends AuthenticationState {}
    
    class AuthenticationUnauthenticated extends AuthenticationState {}
    
    class AuthenticationLoading extends AuthenticationState {}
    
    여기서 우리는 네 가지 초기화되지 않은 인증 상태를 정의했다. 이것은 응용 프로그램이 데이터베이스에 사용자가 존재하는지 확인하기 위해 기다리는 상태에 대응하고, 불러오는 상태는 우리가 응용 프로그램이 영패를 저장하거나 삭제할 때 기다리는 상태이다.유효성 검사 상태는 로그인한 사용자에 해당하고 유효성 검사/로그아웃하지 않은 사용자에 해당합니다.
  • 저희 인증 그룹에 이벤트를 정의하고 bloc_login/bloc/authentication_state.dart 사용자를 수정하고 다음 코드를 추가합니다.
  • part of 'authentication_bloc.dart';
    
    abstract class AuthenticationEvent extends Equatable {
      const AuthenticationEvent();
    
      @override
      List<Object> get props => [];
    }
    
    class AppStarted extends AuthenticationEvent {}
    
    class LoggedIn extends AuthenticationEvent {
      final User user;
    
      const LoggedIn({@required this.user});
    
      @override
      List<Object> get props => [user];
    
      @override
      String toString() => 'LoggedIn { user: $user.username.toString() }';
    }
    
    class LoggedOut extends AuthenticationEvent {}
    
    이것은 발생할 수 있는 세 가지 이벤트에 대응합니다. AppStarted는 블록에 사용자가 존재하는지 확인하는 것을 알려 줍니다. Loggedin은 사용자가 성공적으로 로그인했음을 표시하는 이벤트이고 Logged Out은 사용자가 로그아웃했음을 알려 줍니다.
  • 현재 우리는 이벤트를 상태에 비추는 bloc를 실현하고 수정bloc_login/bloc/authentication_event.dart하며 다음과 같은 내용을 추가해야 한다.
  • import 'dart:async';
    
    import 'package:bloc/bloc.dart';
    import 'package:meta/meta.dart';
    import 'package:equatable/equatable.dart';
    
    import 'package:bloc_login/repository/user_repository.dart';
    import 'package:bloc_login/model/user_model.dart';
    
    part 'authentication_event.dart';
    part 'authentication_state.dart';
    
    class AuthenticationBloc
        extends Bloc<AuthenticationEvent, AuthenticationState> {
      final UserRepository userRepository;
    
      AuthenticationBloc({@required this.userRepository})
          : assert(UserRepository != null);
    
      @override
      AuthenticationState get initialState => AuthenticationUnintialized();
    
      @override
      Stream<AuthenticationState> mapEventToState(
        AuthenticationEvent event,
      ) async* {
        if (event is AppStarted) {
    
          final bool hasToken = await userRepository.hasToken();
    
          if (hasToken) {
            yield AuthenticationAuthenticated();
          } else {
            yield AuthenticationUnauthenticated();
          }
        }
    
        if (event is LoggedIn) {
          yield AuthenticationLoading();
    
          await userRepository.persistToken(
            user: event.user
          );
          yield AuthenticationAuthenticated();
        }
    
        if (event is LoggedOut) {
          yield AuthenticationLoading();
    
          await userRepository.delteToken(id: 0);
    
          yield AuthenticationUnauthenticated();
        }
      }
    }
    
    여기서 우리는 다음과 같은 일을 했다.
    - 인증할 초기화 상태가 초기화되지 않았습니다.
    - 데이터베이스에 존재하는 사용자에 대응하는 AuthenticationAuthenticated 상태가 생성됩니다.이것은 우리가 램에서 프로그램을 제거해도 사용자가 존재하기 때문에 상태의 지속성에 도움이 될 것이다.
    - 이벤트가 Loggedin인 경우 정의된persistToken 함수를 호출하여 사용자를 데이터베이스에 저장합니다.
    - 이벤트가 LoggedOut이면 데이터베이스에서 사용자를 삭제합니다.
  • UI에 들어가서 초기 화면, 파일 bloc_login/bloc/authentication_bloc.dart 및 다음 코드를 만듭니다.
  • import 'package:flutter/material.dart';
    
    class SplashPage extends StatelessWidget {
      @override
      Widget build (BuildContext context) {
        return Scaffold(
          body: Center(
            child: Text('Splash Screen'),
          ),
        );
      }
    }
    
    또한 이 코드는 파일 bloc_login/splash_page.dart 에서 안내되어 액세스를 용이하게 합니다.
    export 'splash_page.dart';
    
  • 사용자들이 로그인할 때 내비게이션을 할 수 있도록 저희도 홈페이지를 만듭니다.따라서 파일bloc_login/splash/splash.dart을 만들고 다음 코드를 추가합니다.
  • import 'package:flutter/material.dart';
    import 'package:flutter_bloc/flutter_bloc.dart';
    import 'package:bloc_login/bloc/authentication_bloc.dart';
    
    class HomePage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Home | Home Hub'),
          ),
          body: Container(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                Padding(padding: EdgeInsets.only(left: 30.0),
                child: Text(
                  'Welcome',
                  style: TextStyle(
                    fontSize: 24.0,
                  ),
                ),),
                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: RaisedButton(
                      child: Text(
                        'Logout',
                        style: TextStyle(
                          fontSize: 24,
                        ),
                      ),
                      onPressed: () {
                        BlocProvider.of<AuthenticationBloc>(context)
                            .add(LoggedOut());
                      },
                      shape: StadiumBorder(
                        side: BorderSide(
                          color: Colors.black,
                          width: 2,
                        ),
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    
    여기에서 사용자를 환영하고 로그아웃하는 단추를 보여 줍니다. 이 단추를 누르면 로그아웃 이벤트가 발생했음을 알려 줍니다.
  • 로그인 상태와 이벤트를 처리하기 위해 로그인 그룹을 만들어야 합니다.따라서, 우리가 만든 bloc_login/home/home_page.dart 디렉터리의 확장자를 사용하여login이라는 다른 블록을 만들고, main.dart에 다음 코드를 추가합니다
  • part of 'login_bloc.dart';
    
    abstract class LoginState extends Equatable {
      const LoginState();
    
      @override
      List<Object> get props => [];
    }
    
    class LoginInitial extends LoginState {}
    
    class LoginLoading extends LoginState {}
    
    class LoginFaliure extends LoginState {
      final String error;
    
      const LoginFaliure({@required this.error});
    
      @override
      List<Object> get props => [error];
    
      @override
      String toString() => ' LoginFaliure { error: $error }';
    }
    
    여기에서 Login Initial 상태는 로그인 폼의 초기 상태이고 Login Loading은 폼 검증 인증서의 상태이며 Login Failure는 로그인 시도가 실패했음을 나타냅니다.
  • 로그인 이벤트를 만들고 수정하십시오bloc_login/login
  • part of 'login_bloc.dart';
    
    abstract class LoginEvent extends Equatable {
      const LoginEvent();
    }
    
    class LoginButtonPressed extends LoginEvent {
      final String username;
      final String password;
    
      const LoginButtonPressed({
        @required this.username,
        @required this.password
      });
    
      @override
      List<Object> get props => [username, password];
    
      @override
      String toString() => 'LoginButtonPressed { username: $username, password: $password }';
    }
    
    또한 로그인 이름을 추가하여 이벤트를 bloc_login/login/bloc/login_states.dart 의 상태로 매핑할 수 있습니다.이 파일에 다음 코드를 추가합니다.
    import 'dart:async';
    
    import 'package:bloc/bloc.dart';
    import 'package:bloc_login/bloc/authentication_bloc.dart';
    import 'package:bloc_login/repository/user_repository.dart';
    import 'package:meta/meta.dart';
    import 'package:equatable/equatable.dart';
    
    part 'login_event.dart';
    part 'login_state.dart';
    
    class LoginBloc extends Bloc<LoginEvent, LoginState> {
      final UserRepository userRepository;
      final AuthenticationBloc authenticationBloc;
    
      LoginBloc({
        @required this.userRepository,
        @required this.authenticationBloc,
      })  : assert(userRepository != null),
            assert(authenticationBloc != null);
    
      @override
      LoginState get initialState => LoginInitial();
    
      @override
      Stream<LoginState> mapEventToState(
        LoginEvent event,
      ) async* {
        if (event is LoginButtonPressed) {
          yield LoginInitial();
    
          try {
            final user = await userRepository.authenticate(
              username: event.username,
              password: event.password,
            );
    
            authenticationBloc.add(LoggedIn(user: user));
            yield LoginInitial();
          } catch (error) {
            yield LoginFaliure(error: error.toString());
          }
        }
      }
    }
    
  • 로그인 양식을 만듭니다.파일bloc_login/login/login_event.dart file and add the following code: 을 만들고 다음 코드를 추가합니다.
  • import 'package:flutter/material.dart';
    import 'package:flutter_bloc/flutter_bloc.dart';
    import 'package:bloc_login/login/bloc/login_bloc.dart';
    
    class LoginForm extends StatefulWidget {
      @override
      State<LoginForm> createState() => _LoginFormState();
    }
    
    class _LoginFormState extends State<LoginForm> {
      final _usernameController = TextEditingController();
      final _passwordController = TextEditingController();
    
      @override
      Widget build(BuildContext context) {
        _onLoginButtonPressed() {
          BlocProvider.of<LoginBloc>(context).add(LoginButtonPressed(
            username: _usernameController.text,
            password: _passwordController.text,
          ));
        }
    
        return BlocListener<LoginBloc, LoginState>(
          listener: (context, state) {
            if (state is LoginFaliure) {
              Scaffold.of(context).showSnackBar(SnackBar(
                content: Text('${state.error}'),
                backgroundColor: Colors.red,
              ));
            }
          },
          child: BlocBuilder<LoginBloc, LoginState>(
            builder: (context, state) {
              return Container(
                child: Form(
                  child: Padding(
                    padding: EdgeInsets.all(40.0),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: <Widget>[
                        TextFormField(
                          decoration: InputDecoration(
                              labelText: 'username', icon: Icon(Icons.person)),
                          controller: _usernameController,
                        ),
                        TextFormField(
                          decoration: InputDecoration(
                              labelText: 'password', icon: Icon(Icons.security)),
                          controller: _passwordController,
                          obscureText: true,
                        ),
                        Container(
                          width: MediaQuery.of(context).size.width * 0.85,
                          height: MediaQuery.of(context).size.width * 0.22,
                          child: Padding(
                            padding: EdgeInsets.only(top: 30.0),
                            child: RaisedButton(
                              onPressed: state is! LoginLoading
                                  ? _onLoginButtonPressed
                                  : null,
                              child: Text(
                                'Login',
                                style: TextStyle(
                                  fontSize: 24.0,
                                ),
                              ),
                              shape: StadiumBorder(
                                side: BorderSide(
                                  color: Colors.black,
                                  width: 2,
                                ),
                              ),
                            ),
                          ),
                        ),
                        Container(
                          child: state is LoginLoading
                              ? CircularProgressIndicator()
                              : null,
                        ),
                      ],
                    ),
                  ),
                ),
              );
            },
          ),
        );
      }
    }
    
  • 또한 파일 bloc_login/login/login_bloc.dart 을 만들고 다음 코드를 추가합니다.
  • import 'package:flutter/material.dart';
    
    import 'package:flutter_bloc/flutter_bloc.dart';
    import 'package:bloc_login/repository/user_repository.dart';
    
    import 'package:bloc_login/bloc/authentication_bloc.dart';
    import 'package:bloc_login/login/bloc/login_bloc.dart';
    import 'package:bloc_login/login/login_form.dart';
    
    class LoginPage extends StatelessWidget {
      final UserRepository userRepository;
    
      LoginPage({Key key, @required this.userRepository})
          : assert(userRepository != null),
            super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Login | Home Hub'),
          ),
          body: BlocProvider(
            create: (context) {
              return LoginBloc(
                authenticationBloc: BlocProvider.of<AuthenticationBloc>(context),
                userRepository: userRepository,
              );
            },
            child: LoginForm(),
          ),
        );
      }
    }
    
    우리는 모두 준비가 되었다. 지금 해야 할 일은 bloc_login/login/login_form.dart 파일을 만들고 로드 표시기를 만드는 것이다.먼저 로드 표시기를 만들고 bloc_login/login/login_page.dart 다음 코드를 추가합니다.
    import 'package:flutter/material.dart';
    
    class LoadingIndicator extends StatelessWidget {
      @override
      Widget build(BuildContext context) => Center(
            child: CircularProgressIndicator(),
          );
    }
    
    또한 다음과 같은 편리한 액세스를 위해 bloc_login/main.dart 출구로 이동합니다.
    export './loading_indicator.dart';
    
  • 마지막으로 bloc_login/common/loading_indicator.dart에 다음 코드를 추가합니다
  • import 'package:flutter/material.dart';
    
    import 'package:bloc/bloc.dart';
    import 'package:flutter_bloc/flutter_bloc.dart';
    import 'package:bloc_login/repository/user_repository.dart';
    
    import 'package:bloc_login/bloc/authentication_bloc.dart';
    import 'package:bloc_login/splash/splash.dart';
    import 'package:bloc_login/login/login_page.dart';
    import 'package:bloc_login/home/home.dart';
    import 'package:bloc_login/common/common.dart';
    
    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: App(userRepository: userRepository),
        )
      );
    }
    
    class App extends StatelessWidget {
      final UserRepository userRepository;
    
      App({Key key, @required this.userRepository}) : super(key: key);
    
      @override
      Widget build (BuildContext context) {
        return MaterialApp(
          theme: ThemeData(
            primarySwatch: Colors.red,
            brightness: Brightness.dark,
          ),
          home: BlocBuilder<AuthenticationBloc, AuthenticationState>(
            builder: (context, state) {
              if (state is AuthenticationUnintialized) {
                return SplashPage();
              }
              if (state is AuthenticationAuthenticated) {
                return HomePage();
              }
              if (state is AuthenticationUnauthenticated) {
                return LoginPage(userRepository: userRepository,);
              }
              if (state is AuthenticationLoading) {
                return LoadingIndicator();
              }
            },
          ),
        );
      }
    }
    
    디버깅을 위해 BlocDelegate를 추가하고 함수를 다시 썼습니다.나는 이것이 좀 긴 게시물이라는 것을 알고 있지만, 나는 그것이 좋은 것일 것이라고 생각한다. 전체 응용 프로그램을 포함하여 여기에 참고로 삼을 것이다.
    이것은 이 시리즈의 마지막 문장이 될 것이다.또한 here 에서 소스 코드를 볼 수 있습니다.
    이전 게시물 링크:
    this repo
    Flutter signup/login application with Django backend #1
    저희가 제공하는 각종 개발 서비스를 얻기 위해 수시로 전화Flutter signup/login application with Django backend #2를 주십시오.

    좋은 웹페이지 즐겨찾기