The main problem is to dynamically refresh the page request data (refresh some controls)

Bloc is created first

/ / bloc import base class'package:flutter/material.dart';

class BaseBlocWidget{

  Stream streams() => null;

  Widget streamBuilder<T>({
    T initalData,
    Function success,
    Function error,
    Function loading,
    Function finished,
    Stream<T> stream,
  }) {
    returnStreamBuilder(//StreamBuilder) Stream: stream, initialData: initalData, Builder: (context, AsyncSnapshot<T> snapshot) {if(finished ! = null) { finished(); }if (snapshot.hasData) {
            if(success ! = null)return success(snapshot.data);
          } else if (snapshot.hasError) {
            if(error ! = null)return error(snapshot.hasError);
          } else {
            if(loading ! = null)returnloading(); }}); }}Copy the code
import 'package:flutter/widgets.dart';
import 'package:flutter_tticar/ui/bloc/BaseBlocWidget.dart';
import 'package:flutter_tticar/ui/comment/http/TTicarWork.dart';
import 'package:flutter_tticar/ui/setting/bean/GoodsCollectBean.dart';
import 'package:rxdart/rxdart.dart'; Class CounterBloc extends BaseBlocWidget {//GoodsCollectBean Returns the resolved bean final _fetcher = new for a network interface request PublishSubject<GoodsCollectBean>(); streams() => _fetcher.stream; voiddispose() {
    if(! _fetcher.isClosed) { _fetcher.close(); Async {}} void fetchQueryList (String pageNum) / / analytical data _refreshDate (pageNum, (map) = > GoodsCollectBean. FromJson (map)); } void _refreshDate(String pageNum, Function handleData) async { new TTicarWork().loadCollectGood(pageNum,"20").listen((request) { try{ _fetcher.sink.add(handleData(request)); }catch(e){fetcher.sink.addError(e,null); }}, onError: (e) {fetcher.sink.addError(e, null); }); }}Copy the code

Page basic logical operations



import 'package:flutter/material.dart';
import 'package:flutter_tticar/ui/comment/http/TTicarWork.dart';
import 'package:flutter_tticar/ui/comment/status/StatusView.dart';
import 'package:flutter_tticar/ui/setting/bean/BaseRequestBean.dart';
import 'package:flutter_tticar/ui/setting/bean/GoodsCollectBean.dart';
import 'package:flutter_tticar/ui/setting/collect/item/GoodsItem.dart';
import 'package:flutter_tticar/ui/setting/myCollectBloc/CounterBloc.dart';
import "package:pull_to_refresh/pull_to_refresh.dart";
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:fluttertoast/fluttertoast.dart'; class GoodsCollectPage extends StatefulWidget { @override GoodsCollectPageState createState() => new GoodsCollectPageState(); } class GoodsCollectPageState extends State<GoodsCollectPage> { CounterBloc _blocProvider = new CounterBloc(); StatusView _statusView = new StatusView(); RefreshController _refreshController; ScrollController _scrollController; int pageNum = 1; // Set page count int pageSize = 1; // Set page number bool refreshUp =true; Bool refresh =false; List<ListBean> dataList = []; @override voidinitState() {// Set the initial data super.initstate (); _blocProvider.fetchQueryList("$pageNum");
    _scrollController = new ScrollController();
    _refreshController = new RefreshController();
  }

  @override
  void dispose() {
    _blocProvider.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return _buildData();
  }

  Widget _buildData() {
    return_blocProvider. StreamBuilder < GoodsCollectBean > (/ / data back callback success: (data) {var request = data as GoodsCollectBean;if(null ! Parse (request.result.size); if (request.result.size) = request.result.size;if (pageNum == 1) {
                dataList.clear();
            }
            dataList.addAll(request.result.list);
          } else if(pageNum = = 1 & request. Success && request. The result. The list. The length = = 0) {/ / countless according to the first pagereturn _statusView.empty("Hide it if you like.");
          } else{// The server is abnormalreturn _statusView.empty(request.msg);
          }
          if (refresh) {
            _refreshController.sendBack(refreshUp, RefreshStatus.completed);
          }
          _refreshController.sendBack(
              false,
              pageSize > pageNum
                  ? RefreshStatus.canRefresh
                  : RefreshStatus.completed);
          return new SmartRefresher(
              enablePullDown: true.enablePullUp: true,
              controller: _refreshController,
              onRefresh: _onRefresh,
              headerBuilder: (context, mode) {
                returnNew ClassicIndicator mode: mode, height: 45.0, releaseText:'Release hand refresh',
                  refreshingText: 'Refreshing',
                  completeText: 'Refresh complete',
                  failedText: 'Refresh failed',
                  idleText: 'Pull refresh',); }, footerBuilder: (context, mode) {return new ClassicIndicator(
                    mode: mode, height: 45, completeText: "Load complete");
              },
              child: new ListView.builder(
                controller: _scrollController,
                itemCount: dataList.length,
                itemBuilder: (context,index){
                  return_getDatas(dataList[index]); })); }, stream: _blocprovider.streams (), // Must set the property error: (MSG) {return_statusView.error(msg); }, loading: () {return_statusView.showLoading(); // load page}); } void _onRefresh(bool up) { refreshUp = up; refresh =true;
    if (up) {
      pageNum = 1;
      //headerIndicator callback
      _refreshDate("$pageNum");
    } else {
      if (pageSize > pageNum) {
        pageNum++;
        //footerIndicator Callback
        _refreshDate("$pageNum"); }}} / / request data void _refreshDate (String pageNum) {_blocProvider. FetchQueryList (pageNum); } Widget _getDatas(ListBean item) {return new Card(
        color: Colors.white,
        elevation: 0,
        margin: new EdgeInsets.only(left: 10, right: 10, top: 10),
        child:new Text("Add your own list data")); }}Copy the code

Default page utility class


import 'package:flutter/material.dart';
import 'package:flutter_tticar/ui/comment/utile/FrameAnimationImage.dart'; Class StatusView {AnimationController controller; Animation<double> animation; List<String> images = []; WidgetshowLoading() {
    for (var i = 0; i < 12; i++) {
      images.add("static/images/donghua_000$i.png");
    }
    return new Container(
      color: Colors.white,
      child: new Center(
        child: new Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new FrameAnimationImage(
              assetList: images,
              width: 100,
              height: 100,
              interval: 100,
            ),
            Text("Loading..."() [(), (), (); } Widget error(Exception msg) { String errMsg="";

    return new Container(
      child: new Center(
        child: new Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Image.asset("static/images/ic_status_view_empty_data.png", width: 100,
                height: 100),
            Text("Server is abnormal. Please try again later."[[(), [(), [(), [(); } Widget empty(msg) {return new Container(
      child: new Center(
        child: new Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Image.asset("static/images/icon_no_collection.png", width: 100,
              height: 100),
            Text("${msg}"[[(), [(), [(), [(); }}Copy the code

Set frame animation

/// frame by FrameAnimation import'package:flutter/material.dart';

class FrameAnimationImage extends StatefulWidget {
  final List<String> assetList;
  final double width;
  final double height;
  final int interval;

  FrameAnimationImage(
      {this.assetList, this.width, this.height, this.interval = 200});

  @override
  State<StatefulWidget> createState() {
    return_FrameAnimationImageState(); }} class _FrameAnimationImageState extends the State < FrameAnimationImage > with SingleTickerProviderStateMixin {/ / animation control Animation<double> _animation; AnimationController _controller; int interval = 200; @override voidinitState() {
    super.initState();

    if(widget.interval ! = null) { interval = widget.interval; } final int imageCount = widget.assetList.length; final int maxTime = interval * imageCount; Controller_controller = new AnimationController(duration: duration (milliseconds: maxTime), vsync: this); _controller.addStatusListener((AnimationStatus status) {if(status = = pleted AnimationStatus.com {_controller. Forward (the from: 0.0); // Start again}}); _animation = new Tween<double>(begin: 0, end: imageCount.toDouble()) .animate(_controller) .. addListener(() {setState(() {// The State that has changed here is the animation object's value}); }); _controller.forward(); } @override voiddispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { int ix = _animation.value.floor() % widget.assetList.length; List<Widget> images = []; // Load all images into the content, otherwise each frame will stallfor (int i = 0; i < widget.assetList.length; ++i) {
      if(i ! = ix) { images.add(Image.asset( widget.assetList[i], width: 0, height: 0, )); } } images.add(Image.asset( widget.assetList[ix], width: widget.width, height: widget.height, ));returnStack(alignment: AlignmentDirectional.center, children: images); }}Copy the code

For network requests, see Dio + Rxdart

The specific effects are as follows