用 Bloc 实现简单的 rxDart 没有得到结果
implementing simple rxDart with Bloc don't get result
从这个 link 在我的网络服务器上作为
http://instamaker.ir/api/v1/getPersons
我正在尝试从该结果中获取结果并打印 avatar
,不幸的是,我使用 rxDart
和 Bloc
的实现没有从该响应中获取结果,我也不知道没有任何错误
服务器响应此简化结果:
{
"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:
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:
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:
class BaseUrl {
static const url = 'http://instamaker.ir';
}
然后InstagramApiProviders
class:
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');
}
}
好吧,这里的答案是我为完成此任务所做的测试的一部分。我可以在这里进行所有测试,但我认为问题的原因是因为 StreamBuilder
是一个小部件,他的 builder
方法回调仅在小部件位于 flutter 小部件树中时被调用。在您的示例中,您只是创建一个 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
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
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();
}
}
小部件UI
这开始显示 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);
}
}
从这个 link 在我的网络服务器上作为
http://instamaker.ir/api/v1/getPersons
我正在尝试从该结果中获取结果并打印 avatar
,不幸的是,我使用 rxDart
和 Bloc
的实现没有从该响应中获取结果,我也不知道没有任何错误
服务器响应此简化结果:
{
"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:
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:
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:
class BaseUrl {
static const url = 'http://instamaker.ir';
}
然后InstagramApiProviders
class:
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');
}
}
好吧,这里的答案是我为完成此任务所做的测试的一部分。我可以在这里进行所有测试,但我认为问题的原因是因为 StreamBuilder
是一个小部件,他的 builder
方法回调仅在小部件位于 flutter 小部件树中时被调用。在您的示例中,您只是创建一个 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
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
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();
}
}
小部件UI
这开始显示 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);
}
}