用Bloc实现简单的rxDart不会得到结果

时间:2019-05-10 14:52:54

标签: flutter bloc rxdart

通过我的Web服务器上的此链接

http://instamaker.ir/api/v1/getPersons

我正在尝试获取结果并从该结果中打印avatar,不幸的是,我使用rxDartBloc的实现未从此响应中获取结果,我也没有得到任何错误

服务器响应此简化结果:

{
  "active": 1,
  "name": "my name",
  "email": " 3 ",
  "loginType": " 3 ",
  "mobile_number": " 3 ",

  ...

  "api_token": "1yK3PvAsBA6r",
  "created_at": "2019-02-12 19:06:34",
  "updated_at": "2019-02-12 19:06:34"
}

main.dart文件:(单击按钮从服务器获取结果)

StreamBuilder(
  stream: bloc.login,
  builder: (context,
      AsyncSnapshot<UserInfo>
      snapshot) {
    if (snapshot.hasData) {
      parseResponse(snapshot);
    }
  },
);
void parseResponse(AsyncSnapshot<UserInfo> snapshot) {
  debugPrint(snapshot.data.avatar);
}

LoginBlock类:

class LoginBlock{
  final _repository = Repository();
  final _login_fetcher = PublishSubject<UserInfo>();

  Observable<UserInfo> get login=>_login_fetcher.stream;

  fetchLogin() async{
    UserInfo userInfo = await _repository.userInfo();
    _login_fetcher.sink.add(userInfo);
  }

  dispose(){
    _login_fetcher.close();
  }
}

final bloc = LoginBlock();

Repository类:

class Repository {
  final userInformation = InstagramApiProviders();

  Future<UserInfo> userInfo() => userInformation.checkUserLogin();
}

我的模型:

class UserInfo {
  int _active;
  String _name;
  ...

  UserInfo.fromJsonMap(Map<String, dynamic> map)
      : _active = map["active"],
        _name = map["name"],
        ...

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['active'] = _active;
    data['name'] = _name;
    ...

    return data;
  }

  //GETTERS
}

BaseUrl类:

class BaseUrl {
  static const url = 'http://instamaker.ir';
}

然后是InstagramApiProviders类:

class InstagramApiProviders {
  Client client = Client();

  Future<UserInfo> checkUserLogin() async {
    final response = await client.get(BaseUrl.url+'/api/v1/getPersons');
    print("entered  "+BaseUrl.url+'/api/v1/getPersons');
    if (response.statusCode == 200) {
      return UserInfo.fromJsonMap(json.decode(response.body));
    } else
      throw Exception('Failed to load');
  }
}

1 个答案:

答案 0 :(得分:0)

好吧,答案是我为完成此任务而进行的测试的一部分。我可以在这里进行所有测试,但是我认为问题原因是因为StreamBuilder是一个窗口小部件,因此只有在窗口小部件位于颤动窗口小部件树中时才调用他的builder方法回调。就像在您的示例中一样,您只是在创建StreamBuilder,因此永远不会调用builder方法,因为该小部件不在小部件树中。

作为建议,首先测试您的代码仅更改UI层...做类似的事情:

@override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        actions: <Widget>[
          IconButton(icon: Icon(Icons.assessment), onPressed: () => loginBlock.fetchLogin()),
        ],
      ),
      body: StreamBuilder<UserInfo>(
        stream: loginBlock.login,
        builder: (context, snapshot){
          if (snapshot.hasData){
            parseResponse(snapshot);
            return Text('user: ${snapshot.data.name} ');
          }
          if (snapshot.hasError)
            return Text('${snapshot.error}');
          else return Text('There is no data');
        },
      ),
    );

在这里,我们将StreamBuilder放在小部件树中,因此调用builder回调,也许您会看到结果。如果失败,请评论我通过此工作用完整的测试代码更新了答案。

使用我进行测试的来源更新答案。

基本模型

class UserInfo {
  int _active;
  String name;

  UserInfo.fromJsonMap(Map<String, dynamic> map) {
    _active = map["active"];
    name = map["name"];
  }

  Map<String, dynamic> toJson() => {
    'active' : _active,
    'name' : name,
  };
} 

提供程序类

class InstagramApiProviders {
  Future<UserInfo> checkUserLogin() async {

    UserInfo info;

    try {
      http.Response resp = await http.get("http://instamaker.ir/api/v1/getPersons");
      if (resp.statusCode == 200){
        print('get response');
        print( resp.body );
        info = UserInfo.fromJsonMap(  Map.from(  json.decode(resp.body ) ));
      }
    }
    catch (ex) {
      throw ex;
    }
    print('returning $info');
    return info;
  }
}

存储库

class Repository {
  final userInformation = InstagramApiProviders();
  Future<UserInfo> userInfo() => userInformation.checkUserLogin().then((user) => user);
}

BLoC类

class LoginBlock{
  final _repository = Repository();
  final _login_fetcher = PublishSubject<UserInfo>();

  Observable<UserInfo> get login=>_login_fetcher.stream;

  fetchLogin() async {
    UserInfo info = await _repository.userInfo();
      _login_fetcher.sink.add(info);
  }

  dispose(){
    _login_fetcher.close();
  }
}

小部件用户界面

这开始显示There is no data消息,但是当您按下appBar按钮时稍等片刻,然后将获取数据并更新UI。

class WidgetToShowData extends StatelessWidget {

  final LoginBlock bloc = LoginBlock();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: <Widget>[
          IconButton(icon: Icon(Icons.assessment), onPressed: () => loginBlock.fetchLogin()),
        ],
      ),
      body: StreamBuilder<UserInfo>(
        stream: loginBlock.login,
        builder: (context, snapshot){
          if (snapshot.hasData){
            parseResponse(snapshot);
            return Text('user: ${snapshot.data.name} ');
          }
          if (snapshot.hasError)
            return Text('${snapshot.error}');
          else return Text('There is no data');
        },
      ),
    );
  }

  void parseResponse(AsyncSnapshot<UserInfo> snapshot) {
    debugPrint(snapshot.data.name);
  }
}