首页 > 解决方案 > 无法通过 ScanStreamTransformer 正确检索模型

问题描述

我正在尝试使用在 Flutter 中实现逻辑的ItemModel流从我的存储库中检索一个类。BLoC

问题是ItemModel找到但未检索到。因此触发了另一个循环并尝试返回一个不同的对象,该对象不在小部件上检索。

样本输出:

I/flutter ( 4520): trying to get 25314126 from cache
I/flutter ( 4520): 25314126 in transformer
I/flutter ( 4520): 25314126 found !! returning: {id: 25314126, type: story, by: xucheng, time: 1607172267, text: , parent: null, kids: [25314805,25314781,25314684,25314664], dead: 0, deleted: 0, url: https://bitbashing.io/std-visit.html, score: 24, title: std::visit is everything wrong with modern C++ (2017), descendants: 4}
I/flutter ( 4520): ----------item to find: 25314126 and found: Instance of 'ItemModel'
I/flutter ( 4520): returned item Instance of 'ItemModel'

在这里找到并检索了正确的对象,但在 UI 上没有收到,因此立即进行另一个搜索:

I/flutter ( 4520): trying to get 25314805 from cache
I/flutter ( 4520): 25314805 found !! returning: {id: 25314805, type: comment, by: vasama, time: 1607178963, text: We got here because adding library features is a lot easier and less risky than adding language features. Work on pattern matching [1] is ongoing, but the bar for entry for a language feature is much higher and as such takes a longer time.<p>1. <a href="http:&#x2F;&#x2F;wg21.link&#x2F;p1371" rel="nofollow">http:&#x2F;&#x2F;wg21.link&#x2F;p1371</a>, parent: 25314126, kids: [], dead: 0, deleted: 0, url: null, score: null, title: null, descendants: 0}
I/flutter ( 4520): ----------item to find: 25314805 and found: Instance of 'ItemModel'
I/flutter ( 4520): returned item Instance of 'ItemModel'

这不是我要检索的对象!!!


总是显示“正在加载 1”字符串

这是我的主要Widget


class NewsDetail extends StatelessWidget{
  final int itemId;

   NewsDetail({ this.itemId}) ;



  @override
  Widget build(BuildContext context) {
    final bloc = CommentsProvider.of(context);


    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text('Detail'),
      ),
      body: buildBody(bloc),

    );
  }

  Widget buildBody(CommentsBloc bloc){
    return StreamBuilder(
        stream: bloc.itemWithComments,
        builder:
            (context, AsyncSnapshot<Map<int,Future<ItemModel>>> snapshot){

          if (!snapshot.hasData){
            return Text('Loading 1');
          }

          final itemFuture = snapshot.data[itemId];

          return FutureBuilder(
              future: itemFuture,
              builder: (context,AsyncSnapshot<ItemModel> itemSnapshot){


                if(!itemSnapshot.hasData){
                  return Text('Loading 2');
                }

                return buildTitle(itemSnapshot.data);
              }
          );

        },);
  }

这表明有问题stream: bloc.itemWithComments,

这是我的 BLOC 课程:

class CommentsBloc{
  final _repository = Repository();
  final _commentsFetcher = PublishSubject<int>();
  final _commentsOutput = BehaviorSubject<Map<int,Future<ItemModel>>>();

  //Streams
  get itemWithComments =>  _commentsOutput.stream;

  //Sink
  Function(int) get fetchItemWithComments => _commentsFetcher.sink.add;

  CommentsBloc(){
    _commentsFetcher.stream.transform(_commentsTransformer()).pipe(_commentsOutput);
  }

  _commentsTransformer (){
    return ScanStreamTransformer(
        (cache,int id,index){
          cache[id] = _repository.fetchItem(id);
          print('$id in transformer');
          cache[id].then((ItemModel item){
            item.kids.forEach((kidId)=>fetchItemWithComments(kidId));

          });
        },
      <int,Future<ItemModel>>{},
    );
  }


  dispose(){
    _commentsFetcher.close();
    _commentsOutput.close();
  }

}

这是我在Repository课堂上获取物品的方式

 List<Source> sources = <Source>[
    newsDbProvider,
    NewsApiProvider(),
  ];
  List<Cache> caches = <Cache>[
   newsDbProvider,
  ];

Future<ItemModel> fetchItem(int id) async{

    ItemModel item;
    var source;

    for(source in sources) {
        item = await source.fetchItem(id);
        print('----------item to find: $id and found: ${item}');
        if(item!=null){
         break;
        }
      }

    for(var cache in caches) {
      if(cache!=source) {
        cache.addItem(item);
      }
    }

    print('returned item ${item}');

    return item;

  }

即使每次都返回一个 Instance 为什么是snapshot.hasData false

另请注意,小部件仅通过 using方法以正确的 id调用一次。我完全错过了什么?onTap

标签: flutterdart

解决方案


即使我使用fetchItemWithComments来下沉物品,我仍然必须在ScanStreamTransformer

_commentsTransformer (){
    return  ScanStreamTransformer<int,Map<int,Future<ItemModel>>>(
        (Map<int,Future<ItemModel>>cache,int id,index){
          print(index);
          cache[id] = _repository.fetchItem(id);
          cache[id].then((ItemModel item){
            item.kids.forEach(  (kidId)   =>   fetchItemWithComments(kidId)  );
          });
          return cache; //was missing this
        },
      <int,Future<ItemModel>>{},
    );
  }

这已经困扰我好几天了,我检查了所有内容,但找不到任何东西,所以如果你正在使用ScanStreamTransformer课程

永远有一个return声明


推荐阅读