问题描述
我正在尝试从互联网上获取一些数据并将其显示为列表.
I am trying to fetch some data from the internet and show it int a list.
以下是我的bloc
代码
class StudentsBloc {
final _repository = Repository();
final _students = BehaviorSubject<StudentModel>();
final BehaviorSubject<bool> _showProgress = BehaviorSubject<bool>();
final BehaviorSubject<bool> _showNoInternetViews = BehaviorSubject<bool>();
Observable<StudentModel> get students => _students.stream;
Observable<bool> get showProgress => _showProgress.stream;
Observable<bool> get showNoInternetViews => _showNoInternetViews.stream;
//FetchStudent from my Api
fetchStudents(String disciplineId, String schoolId, String year_id,
String lastIndex) async {
final student = await _repository.fetchStudents(
disciplineId, schoolId, year_id, lastIndex);
_students.sink.add(student);
}
//Check to see if user has internet or not
isNetworkAvailable(String disciplineId, String schoolId, String year_id,
String lastIndex) async {
checkInternetConnection().then((isAvailable) {
if (isAvailable) {
fetchStudents(disciplineId, schoolId, year_id, lastIndex);
} else {
_students.sink.addError(NO_NETWORK_AVAILABLE);
}
});
}
Function(bool) get changeVisibilityOfProgress => _showProgress.sink.add;
Function(bool) get changeVisibilityOfNoInternetViews =>
_showNoInternetViews.sink.add;
dispose() {
_students.close();
_showProgress.close();
_showNoInternetViews.close();
}
}
以下是我隐藏统一控件的主要代码
Following is my main code to hide unide Widgets
Widget buildList(StudentsBloc bloc) {
return StreamBuilder(
stream: bloc.students,
builder: (context, AsyncSnapshot<StudentModel> snapshot) {
if (snapshot.hasError) {
bloc.changeVisibilityOfProgress(false);
bloc.changeVisibilityOfNoInternetViews(true);
return StreamBuilder(
stream: bloc.showNoInternetViews,
builder: (context, snapshot) {
bool showNoInternetView = snapshot.hasData ?? false;
return Visibility(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("No Network Available"),
RaisedButton(
onPressed: () {
fetchStudents();
},
child: Text("Retry"),
)
],
),
),
visible: showNoInternetView ? true : false,
);
},
);
}
if (snapshot.hasData) {
bloc.changeVisibilityOfProgress(false);
bloc.changeVisibilityOfNoInternetViews(false);
return Refresh(
year_id: "2",
schoolId: "1",
lastIndex: "0",
disciplineId: "1",
child: ListView.builder(
itemBuilder: (context, int index) {
return buildTile(
snapshot.data.toBuilder().data.studentData[index]);
},
itemCount: snapshot.data.toBuilder().data.studentData.length,
),
);
}
if (!snapshot.hasData) {
return StreamBuilder(
builder: (context, snapshot) {
bool showProgressIndicator = snapshot.data ?? false;
return Visibility(
child: Center(
child: CircularProgressIndicator(),
),
visible: showProgressIndicator ? true : false,
);
},
stream: bloc.showProgress,
);
}
},
);
}
在Scaffold
的body
中调用buildList
方法
void fetchStudents() {
bloc?.changeVisibilityOfNoInternetViews(false);
bloc?.changeVisibilityOfProgress(true);
bloc?.isNetworkAvailable("1", "1", "2", "0");
}
假设打开应用程序时用户已连接互联网,然后我就能看到circularprogressindicator
,然后可以看到数据列表但假设开始时打开应用程序且用户没有互联网,那么我会显示无网络可用文本"和一个重试按钮,现在,如果用户已连接到Internet,然后单击按钮重试,那么几秒钟后我将直接看到数据列表,而不是circularprogressindicator
.我无法理解为什么NoInternetviews
没有隐藏并且.
Suppose the user has internet when app is opened then i am able to see circularprogressindicator
and then the list of data is visiblebut suppose at the start when app is opened and the user does not have internet then i am showing the No Network Available Text and a button to retry,now if the user has connected to the internet and then click on button to retry i am directly seeing the list of data after few seconds instead of the circularprogressindicator
.I am not able to understand why the NoInternetviews
are not hiding and progressindicator
is showing when retry button is clicked before showing list of data.
我的流在调用的重试按钮上没有得到更新.在StreamBuilder
中是否有针对StreamBuilder
的警告?
My stream is not getting updated on retry button called. Are there any caveats for StreamBuilder
within StreamBuilder
?
我尝试更改答案中@ivenxu提到的StreamBuilder
顺序,但仍然不起作用.以下是附加代码的链接 https://drive.google.com/file/d/15Z8jXwwOpwTB1CxDS8sHz8 view?usp = sharing https://drive.google.com/open?id=1gIXV20S1o5jYRnno_NADabuIj4w163fF
I tried changing the StreamBuilder
order as mentioned by @ivenxu in the answer but it still does not work.Following are the links of attached codehttps://drive.google.com/file/d/15Z8jXw1OpwTB1CxDS8sHz8jKyHhLwJp7/view?usp=sharinghttps://drive.google.com/open?id=1gIXV20S1o5jYRnno_NADabuIj4w163fF
推荐答案
在视图层中,可以使用 Visibility()小部件并在从Internet加载数据时传递可见参数true或false.让我们考虑一下如何从bloc更改可见变量. Visibility()的父级使用 StreamBuilder()小部件以流式传输更改数据.对于您的情况,您需要在区块内部添加 PublishSubject 来流式传输和添加新数据,并且需要 Observable 来在小部件上流式传输这些数据.
in view layer you can use Visibility() widget and pass visible parameter true or false when load data from Internet.let's think about how to change the visible variable from bloc.The parent of Visibility() widget the StreamBuilder() to stream on changes data.for your case you need a PublishSubject inside your bloc to stream and add new data, and Observable to stream on this data on your widget.
让我们显示一个代码段代码,以帮助您实现它
let's show a snippet code to help you how you can implement it
该集团包含 PublishSubject 和 Observable 以便流式传输和添加数据
The bloc contains PublishSubject and Observable to stream and add data
//this Subject allows sending data, error and done events to the listener
final PublishSubject<bool> _progressStateSubject = new PublishSubject();
//the listener are streaming on changes
Observable<bool> get progressStateStream => _progressStateSubject.stream;
//to change your progress state
void changeProgressState({bool state}) => _progressStateSubject.sink.add(state);
您可以在此处更改进度状态
Here you can change your state of your progress
void callWebService() async {
//when you call your func to fetch your data change your state to true
changeProgressState(state: true);
.
.
.
if(response != null){
//when your call is done change the state to false
changeProgressState(state: false);
}
}
您的进度小部件是
// Loading Widget
Widget _buildLoadingWidget(Bloc bloc) {
return StreamBuilder<bool>(
stream: bloc.progressStateStream,//streaming on changes
builder: (context, snapshot) {
return Visibility(
visible: snapshot.data ?? false,//calling when data changes
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("Loading data from API...",
textDirection: TextDirection.ltr),
CircularProgressIndicator()
],
),
),
);
});
}
这篇关于Bloc Pattern隐藏和取消隐藏小部件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!