颤振:版本0.2.8打破了以前工作的代码

时间:2018-04-14 01:29:49

标签: flutter

在我更新到flutter的新版本之前(见下文),一切正常。 现在它不再有用了。

以下代码执行gridView

的“分页”加载

有人可以告诉我Flutter的最新版本有什么变化以及如何解决这个问题?

非常感谢

Flutter版本:

flutter --version
Flutter 0.2.8 • channel beta • https://github.com/flutter/flutter.git
Framework • revision b397406561 (11 days ago) • 2018-04-02 13:53:20 -0700
Engine • revision c903c217a1
Tools • Dart 2.0.0-dev.43.0.flutter-52afcba357

以下是以前使用的代码:

typedef Future<PageAnswer> ApiPageRequest(int page, int pageSize);

class MIDApi {
  ///
  /// Returns the list of items belonging to the active profile
  /// 
  Future<PageAnswer> getItems({
    int pageIndex: 0,
    int pageSize: 50,
    @required String sortOrder
  }) async {
    String url = "ItemsList/$sortOrder";

    return ajaxGet(url).then((String responseBody) async {
//      print(responseBody);
      final Map response = json.decode(responseBody);
      final _status = response["status"];
      if (_status == "OK"){
          // Everything is OK
          Map map = json.decode(response["data"]);
          List<Map> objects = map["List"];
          int total = map["Total"];
          return new PageAnswer(objects, total);
      }

      return Null;
    }).catchError((){
      return Null;
    });
  }
}

///
/// This widget is used to display a "paged" GridView
/// 
/// Invocation example:
///   new PagedGridView<Map>(request, widgetAdapter: adapt);
/// 
/// where: request could be
/// Future<List<Map>> request(int page, int pageSize) async {
///   routine to fetch the data from the server
/// }
/// 
/// and adapt could be:
/// Widget adapt(Map map){
///   return new MyWidget(map);
/// }
/// 
class PagedGridView extends StatefulWidget {
  /// Abstraction for loading the data.
  /// This can be anything: An API-Call,
  /// loading data from a certain file or database,
  /// etc.  If will deliver a list of objects (of type T)
  final ApiPageRequest pageRequest;

  /// The number of columns per row of the grid
  final int numberColumns;

  /// The number of elements requested for each page
  final int pageSize;

  /// The number of left-over elements in list which
  /// will trigger loading the next page
  final int pageThreshold;

  /// Used for building Widgets out of the fetched data
  final WidgetAdapter<Map> widgetAdapter;
  final bool reverse;

  final Indexer<Map> indexer;
  final Stream<Map> topStream;

  /// Constructor
  const PagedGridView({
    Key key,
    this.numberColumns: 2,
    this.pageSize: 50,
    this.pageThreshold: 10,
    @required this.pageRequest,
    @required this.widgetAdapter,
    this.reverse: false,
    this.indexer,
    this.topStream
  }): super(key: key);

  @override
  State<StatefulWidget> createState() {
    return new PagedGridViewState();
  }
}

class PagedGridViewState extends State<PagedGridView> {

  /// Contains all fetched elements ready to display
  List<Map> objects = [];

  /// Total number of objects that could be returned
  int total = -1;

  /// A Future returned by loadNext() if there
  /// is currently a request running
  /// or null, if no request is performed
  Future request;

  Map<int, int> index = {};

  void doSomething(){
    print("I need to do something");
  }

  void Clear() async {
    await onRefresh();
  }

  @override
  void initState(){
    super.initState();

    /// At start, let's systematically try to fetch some data
    this.lockedLoadNext();

    if (widget.topStream != null){
      widget.topStream.listen((Map t){
        setState((){
          this.objects.insert(0, t);
          this.reIndex();
        });
      });
    }
  }

  @override
  Widget build(BuildContext context){
    GridView listView = new GridView.builder(
      gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: widget.numberColumns),
      itemBuilder: itemBuilder,
      itemCount: objects.length,
      reverse: widget.reverse
    );

    RefreshIndicator refreshIndicator = new RefreshIndicator(
      onRefresh: onRefresh,
      child: listView
    );

    return new NotificationListener<ListElementUpdate<Map>>(
        child: refreshIndicator,
        onNotification: onUpdate
    );
  }

  Widget itemBuilder(BuildContext context, int index){
    /// If we are entering the threshold zone, 
    /// try to fetch additional objects
    if (index + widget.pageThreshold > objects.length){
      notifyThreshold();
    }

    return widget.widgetAdapter != null ? widget.widgetAdapter(objects[index])
      : new Container();
  }

  void notifyThreshold(){
    lockedLoadNext();
  }

  bool onUpdate(ListElementUpdate<Map> update){
    if (widget.indexer == null){
      debugPrint('ListElementUpdate on un-indexed list');
      return false;
    }
    int index = this.index[update.key];
    if (index == null){
      debugPrint('ListElementUpdate index not found');
      return false;
    }

    setState((){
      this.objects[index] = update.instance;
    });

    return true;
  }

  Future onRefresh() async {
    this.request?.timeout(const Duration());
    PageAnswer answer = await widget.pageRequest(0, widget.pageSize);
    List<Map> fetched = answer.list;
    total = answer.total;

    setState(() {
      this.objects.clear();
      this.index.clear();
      this.addObjects(fetched);
    });

    return true;
  }

  ///
  /// This routine only fetches new data, if no other request is pending
  /// 
  void lockedLoadNext() {
    if (this.request == null) {
      this.request = loadNext().then((x) {
        this.request = null;
      });
    }
  }

  Future loadNext() async {
    // If there is no need to fetch any further data, simply return
    if (objects.length >= total && total != -1){
      return Null;
    }

    int page = (objects.length / widget.pageSize).floor();
    PageAnswer answer = await widget.pageRequest(page, widget.pageSize);
    List<Map> fetched = answer.list;
    total = answer.total;

    if (mounted) {
      this.setState(() {
        addObjects(fetched);
      });
    }
  }

  void addObjects(Iterable<Map> objects) {
    objects.forEach((Map object) {
      int index = this.objects.length;
      this.objects.add(object);
      if (widget.indexer != null) {
        this.index[widget.indexer(object)] = index;
      }
    });
  }

  void reIndex(){
    this.index .clear();
    if (widget.indexer!=null){
      int i = 0;
      this.objects.forEach((object){
        index[widget.indexer(object)] == i;
        i++;
      });
    }
  }
}

调用代码:

class ItemsPage extends StatefulWidget {
  @override
  _ItemsPageState createState() => new _ItemsPageState();
}

class _ItemsPageState extends State<ItemsPage> {
  static final GlobalKey<PagedGridViewState> _gridKey = new GlobalKey<PagedGridViewState>();
  String _path = mid.serverHttps ? "https://${mid.serverUrl}/"
                                 : "http://${mid.serverUrl}/";
  String _sortOrder;
  final List<SortMethod> sortMethods = const <SortMethod>[
    const SortMethod(value: 'alpha',  title: "Alpha", icon: Icons.sort_by_alpha),
    const SortMethod(value: 'older_first', title: "Older first", icon: Icons.autorenew),
    const SortMethod(value: 'last_first', title: "Last first", icon: Icons.change_history),
  ];

  Future<PageAnswer> request(int page, int pageSize) async {
    PageAnswer answer = await mid.api.getItems(sortOrder: _sortOrder);
    return answer;
  }

  void _handleTap(int lookId) {
    print('tap:' + lookId.toString());
  }


  Widget adapt(Map map){
    var photos = map["Photos"].split(";");
    String photoName = photos[0].split("|")[0];

    return new GestureDetector(
              onTap: () {_handleTap(map["Id"]);},
              child: new GridTile(
                child: new Card(
                  child: new Stack(
                    fit: StackFit.expand,
                    children: <Widget>[
                      new Image.network(_path + photoName,
                          fit: BoxFit.fitHeight),
                      new Center(
                          child: new Text(
                        map["Title"],
                        textAlign: TextAlign.center,
                      )),
                    ],
                  ),
                ),
              ),
            );
  }

  _onSortOrderChanged(String value) {
    setState((){
      _sortOrder = value;
      _gridKey.currentState.Clear();
    });
  }

  @override
  void initState(){
    super.initState();
    _sortOrder = 'alpha';
  }

  @override
  Widget build(BuildContext context) {
    PagedGridView grid = new PagedGridView(
      key: _gridKey,
      pageRequest: request,
      widgetAdapter: adapt,
      numberColumns: 2,
    );

    DropdownButton ddl = new DropdownButton<String>(
            value: _sortOrder,
            items: sortMethods.map((SortMethod sort){
              return new DropdownMenuItem(
                value: sort.value,
                child: new Row(children: <Widget>[new Icon(sort.icon), new Text(sort.title)],)
              );
            }).toList(),
             onChanged: _onSortOrderChanged,
    );

    PopupMenuButton<ItemSorting> popSort = new PopupMenuButton<ItemSorting>(
      icon: new Icon(Icons.sort),
      itemBuilder: (BuildContext context) => <PopupMenuItem<ItemSorting>> [
        const PopupMenuItem<ItemSorting>(
          value: ItemSorting.alpha,
          child: const Text('Sort Alpha')
        ),
        const PopupMenuItem<ItemSorting>(
          value: ItemSorting.last_first,
          child: const Text('Sort Last First')
        ),
        const PopupMenuItem<ItemSorting>(
          value: ItemSorting.older_first,
          child: const Text('Sort Older First')
        )
      ],
      onSelected: (ItemSorting action){
        _onSortOrderChanged(action.toString().split('.')[1]);
      },
    );  

    return new Scaffold(
      appBar: new AppBar(
        title: new Text('My Items'),
        actions: <Widget>[
          popSort, //ddl,
        ],
      ),
      body: new Center(
        child: grid,
      ),
    );
  }
}

class SortMethod {
  const SortMethod({this.title, this.icon, this.value});
  final String title;
  final IconData icon;
  final String value;
}

错误堆栈:

E/flutter (15195): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter (15195): type 'Future<Object>' is not a subtype of type 'FutureOr<PageAnswer>' where
E/flutter (15195):   Future is from dart:async
E/flutter (15195):   Object is from dart:core
E/flutter (15195):   FutureOr is from dart:async
E/flutter (15195):   PageAnswer is from file:///D:/Development/appli/lib/libraries/function_types.dart
E/flutter (15195):
E/flutter (15195): #0      MIDApi.getItems (file:///D:/Development/appli/lib/libraries/api.dart:35:8)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #1      _ItemsPageState.request (file:///D:/Development/appli/lib/pages/items.dart:30:39)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #2      PagedGridViewState.loadNext (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:191:38)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #3      PagedGridViewState.lockedLoadNext (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:178:22)
E/flutter (15195): #4      PagedGridViewState.initState (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:93:10)
E/flutter (15195): #5      StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3734:58)
E/flutter (15195): #6      ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
E/flutter (15195): #7      Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #8      Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
E/flutter (15195): #9      SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4637:14)
E/flutter (15195): #10     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #11     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
E/flutter (15195): #12     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
E/flutter (15195): #13     Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
E/flutter (15195): #14     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
E/flutter (15195): #15     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
E/flutter (15195): #16     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #17     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
E/flutter (15195): #18     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
E/flutter (15195): #19     Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
E/flutter (15195): #20     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
E/flutter (15195): #21     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
E/flutter (15195): #22     ParentDataElement.mount (package:flutter/src/widgets/framework.dart:3938:11)
E/flutter (15195): #23     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #24     MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4742:32)
E/flutter (15195): #25     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #26     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
E/flutter (15195): #27     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
E/flutter (15195): #28     Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
E/flutter (15195): #29     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
E/flutter (15195): #30     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3752:11)
E/flutter (15195): #31     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
E/flutter (15195): #32     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #33     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
E/flutter (15195): #34     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
E/flutter (15195): #35     Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
E/flutter (15195): #36     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
E/flutter (15195): #37     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
E/flutter (15195): #38     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #39     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
E/flutter (15195): #40     ComponentElement.performRebuild (packag
E/flutter (15195): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter (15195): type 'Future<Object>' is not a subtype of type 'FutureOr<PageAnswer>' where
E/flutter (15195):   Future is from dart:async
E/flutter (15195):   Object is from dart:core
E/flutter (15195):   FutureOr is from dart:async
E/flutter (15195):   PageAnswer is from file:///D:/Development/appli/lib/libraries/function_types.dart
E/flutter (15195):
E/flutter (15195): #0      MIDApi.getItems (file:///D:/Development/appli/lib/libraries/api.dart:34:8)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #1      _ItemsPageState.request (file:///D:/Development/appli/lib/pages/items.dart:30:39)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #2      PagedGridViewState.onRefresh (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:160:38)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #3      PagedGridViewState.Clear (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:85:11)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #4      _ItemsPageState._onSortOrderChanged.<anonymous closure> (file:///D:/Development/appli/lib/pages/items.dart:67:29)
E/flutter (15195): #5      State.setState (package:flutter/src/widgets/framework.dart:1108:30)
E/flutter (15195): #6      _ItemsPageState._onSortOrderChanged (file:///D:/Development/appli/lib/pages/items.dart:65:5)
E/flutter (15195): #7      _ItemsPageState.build.<anonymous closure> (file:///D:/Development/appli/lib/pages/items.dart:114:9)
E/flutter (15195): #8      _PopupMenuButtonState.showButtonMenu.<anonymous closure> (package:flutter/src/material/popup_menu.dart)
E/flutter (15195): #9      _RootZone.runUnary (dart:async/zone.dart:1381:54)
E/flutter (15195): #10     _FutureListener.handleValue (dart:async/future_impl.dart:129:18)
E/flutter (15195): #11     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:633:45)
E/flutter (15195): #12     Future._propagateToListeners (dart:async/future_impl.dart:662:32)
E/flutter (15195): #13     Future._completeWithValue (dart:async/future_impl.dart:477:5)
E/flutter (15195): #14     Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:507:7)
E/flutter (15195): #15     _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
E/flutter (15195): #16     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
I/flutter (15195): Another exception was thrown: type '() => Future<dynamic>' is not a subtype of type '() => Future<Null>'
E/flutter (15195): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter (15195): type '() => Type' is not a subtype of type '(Object) => FutureOr<Object>'
E/flutter (15195): #0      _FutureListener.handleError (dart:async/future_impl.dart:145:11)
E/flutter (15195): #1      Future._propagateToListeners.handleError (dart:async/future_impl.dart:645:47)
E/flutter (15195): #2      Future._propagateToListeners (dart:async/future_impl.dart:666:24)
E/flutter (15195): #3      Future._completeError (dart:async/future_impl.dart:485:5)
E/flutter (15195): #4      _SyncCompleter._completeError (dart:async/future_impl.dart:55:12)
E/flutter (15195): #5      _Completer.completeError (dart:async/future_impl.dart:27:5)
E/flutter (15195): #6      MIDApi.getItems.<anonymous closure> (file:///D:/Development/appli/lib/libraries/api.dart)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #7      _RootZone.runUnary (dart:async/zone.dart:1381:54)
E/flutter (15195): #8      _FutureListener.handleValue (dart:async/future_impl.dart:129:18)
E/flutter (15195): #9      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:633:45)
E/flutter (15195): #10     Future._propagateToListeners (dart:async/future_impl.dart:662:32)
E/flutter (15195): #11     Future._complete (dart:async/future_impl.dart:467:7)
E/flutter (15195): #12     _SyncCompleter.complete (dart:async/future_impl.dart:51:12)
E/flutter (15195): #13     ajaxGet (file:///D:/Development/appli/lib/libraries/ajax.dart)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #14     MIDApi.getItems (file:///D:/Development/appli/lib/libraries/api.dart:21:12)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #15     _ItemsPageState.request (file:///D:/Development/appli/lib/pages/items.dart:30:39)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #16     PagedGridViewState.onRefresh (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:160:38)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #17     PagedGridViewState.Clear (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:85:11)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #18     _ItemsPageState._onSortOrderChanged.<anonymous closure> (file:///D:/Development/appli/lib/pages/items.dart:67:29)
E/flutter (15195): #19     State.setState (package:flutter/src/widgets/framework.dart:1108:30)
E/flutter (15195): #20     _ItemsPageState._onSortOrderChanged (file:///D:/Development/appli/lib/pages/items.dart:65:5)
E/flutter (15195): #21     _ItemsPageState.build.<anonymous closure> (file:///D:/Development/appli/lib/pages/items.dart:114:9)
E/flutter (15195): #22     _PopupMenuButtonState.showButtonMenu.<anonymous closure> (package:flutter/src/material/popup_menu.dart)
E/flutter (15195): #23     _RootZone.runUnary (dart:async/zone.dart:1381:54)
E/flutter (15195): #24     _FutureListener.handleValue (dart:async/future_impl.dart:129:18)
E/flutter (15195): #25     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:633:45)
E/flutter (15195): #26     Future._propagateToListeners (dart:async/future_impl.dart:662:32)
E/flutter (15195): #27     Future._completeWithValue (dart:async/future_impl.dart:477:5)
E/flutter (15195): #28     Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:507:7)
E/flutter (15195): #29     _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
E/flutter (15195): #30     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)

0 个答案:

没有答案