Обрабатывать ответ обратного вызова из метода Post с помощью блока

#flutter #dart #bloc

#flutter #dart #блок

Вопрос:

Я вызываю login api при нажатии кнопки, я могу получить ответ от сервера, но при нажатии на кнопку я не могу получить ответ.Как я могу получить ответ и обработать его.Для этого я использую шаблон блока. Вот код,

 import 'package:flutter/material.dart';
import '../blocs/bloc.dart';
import '../blocs/provider.dart';
import '../models/login_response.dart';

class LoginScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Provider(
  child: new Scaffold(
      body: Container(
        child: LoginForm(),
    ),
  ),
);
}
}

class LoginForm extends StatefulWidget {
// since its a stateful widget we need to create state for it.
const LoginForm({Key key}) : super(key: key);

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

class _LoginFormState extends State<LoginForm> {

@override
 Widget build(BuildContext context) {


return Form(
  child: Column(
    children: <Widget>[ 
      Padding(
        padding: const EdgeInsets.only(top: 50),
      ),
      // Start creating widget here.
      emailField(),
      passwordField(),
      Container(margin: EdgeInsets.only(top: 25.0)),
      submitButton()
    ],
  ),
 );
}

  Widget emailField() {
   return StreamBuilder(
   stream: bloc.email,
   builder: (context, snapshot) {
     return TextField(
        onChanged:  bloc.changeEmail,
        keyboardType: TextInputType.emailAddress,
        decoration: InputDecoration(
        hintText: 'you@example.com',
        labelText: 'Email Address',
        errorText: snapshot.error
      ),
    );
   }
  );
}

Widget passwordField() {
  return StreamBuilder(
   stream: bloc.password,
    builder: (context, snapshot) {
      return TextField(
        onChanged: bloc.changePassword,
        obscureText: true,
        decoration: InputDecoration(
        labelText: 'Please enter your password',
        hintText: 'Password',
        errorText: snapshot.error
      ),
    );
   },
 );
}

Widget submitButton() {

return StreamBuilder(
  stream: bloc.submitValid,
  builder: (context, snapshot) {
      return RaisedButton(
        onPressed:() =>  showWidgetForNetworkCall(context),
        // onPressed: () {
        //   // Do submit button action.              
        //   showWidgetForNetworkCall(context);
        // //  callLoginApi();
        // },
        child: const Text('Login'),
        textColor: Colors.white,
        color: Colors.blueAccent,
      );
    },
  );
}

  // Loading Widget
   Widget _buildLoadingWidget() {
   return Center(
     child: Column(
       mainAxisAlignment: MainAxisAlignment.center,
       children: <Widget>[
         Text("Loading data from API...", textDirection: TextDirection.ltr), CircularProgressIndicator()
       ],
     ),
   );
 }

 // // Error Widget
  Widget _buildErrorWidget(String error) {
   return Center(
    child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: <Widget>[
      Text("Loading error data from API...", textDirection: TextDirection.ltr), CircularProgressIndicator()
    ],
   ),
 );
}

// show server data
 showServerData() {
   print(" Servr >>>>>> Data : ");
 }

 Widget showWidgetForNetworkCall(BuildContext context) {
  bloc.loginSubmit();
    return StreamBuilder(
     stream: bloc.loginSubject.stream,
       builder: (context, AsyncSnapshot<LoginResponse>snapshot){
     if (snapshot.hasData) {
        return showServerData();
      } else if (snapshot.hasError) {
        return _buildErrorWidget(snapshot.error);
      } else {
        return _buildLoadingWidget();
      }
    },
  );
 }
}
  

Это мой login_screen.dart. И мой класс блока для вызова api является:

    postData() async {
LoginResponse response = await _repository.postData(_loginResource);
_subject.sink.add(response);

}
  

код блока

 import 'dart:async';
import 'package:rxdart/rxdart.dart';
import 'validators.dart';
import '../models/login_response.dart';
import '../repository/login_repository.dart';
import '../resources/login_resource.dart';

class Bloc extends Object with Validators {

final LoginRepository _repository = LoginRepository();
final BehaviorSubject<LoginResponse> _subject = 
BehaviorSubject<LoginResponse>();
LoginResource _loginResource = LoginResource();

final _email = BehaviorSubject<String>(); // Declaring variable as private
final _password = BehaviorSubject<String>(); // Declaring variable as private

// Add data to stream (Its like setter)
Stream<String> get email => _email.stream.transform(validateEmail);
Stream<String> get password => 
 _password.stream.transform(validatePassword);
 Stream<bool> get submitValid => Observable.combineLatest2(email, password, (e, p) => true);

 // Change data. For retrieveing email value.
 Function(String) get changeEmail => _email.sink.add;
 Function(String) get changePassword => _password.sink.add;

 loginSubmit() {

  _loginResource.email = "bar1";
  _loginResource.password = "bar2";

  postData();
}

 postData() async {
   LoginResponse response = await _repository.postData(_loginResource);
   _subject.sink.add(response);
 }

  dispose() {
   _email.close();
   _password.close();
   _subject.close();
  }

  BehaviorSubject<LoginResponse> get loginSubject => _subject;
}
  

окончательный блок = Bloc();

Комментарии:

1. Множество потоков и приемников кажутся очень сложными и, вероятно, станут слишком сложными, как только появится логика с более чем 2 полями. Взгляните на пакет flutter_bloc , который действительно хорошо реализует шаблон блока. Одним из их примеров является поток входа / аутентификации .

2. Я думаю, решаемая, если вам нужно больше деталей течет. medium.com/swlh /…