1

问题很简单,但我找不到合适的解决方案。我有一个搜索屏幕,这就是我想要做的。

  • 第一次启动屏幕时,我想在Text小部件中显示一条消息“您的结果将出现在此处”。
  • 如果用户在搜索框中输入内容并按搜索,我想显示CircularProgressIndicator.
  • 然后,当收到 API 响应时,我想显示ListViewText说“什么也没找到”。
  • 如果用户再次搜索某些内容,我想CircularProgressIndicator再次显示。

如何使用 实现这种行为Stream?以下是我到目前为止的代码:

小部件

StreamBuilder<List<Model>>(
  stream: bloc.searchStream,
  builder: (context, snapshot) {

    if (snapshot.hasError) {
      return Center(
        child: Text(
          'Error occurred'
        ),
      );
    }

    if (!snapshot.hasData) {
      return Center(
        child: Text(
          'Your results will appear here'
        ),
      );
    }

    if (snapshot.hasData && snapshot.data.length < 1) {
      return Center(
        child: Text(
          'Found nothing'
        ),
      );
    }

    // Where should I put my CircularProgressIndicator?

    return ListView.separated(
      itemCount: snapshot.data.length,
      separatorBuilder: (context, index) => Divider(height: 1),
      itemBuilder: (context, index) {
        final item = snapshot.data[index];
        return ItemWidget(item);
      },
    );
  },
)

集团

final _searchStreamController = StreamController<List<Model>>();
Stream<List<Model>> get searchStream => _searchStreamController.stream;

void search(String searchTerm) async {

  if (searchTerm.isEmpty) {
    _searchStreamController.add(null);
    return;
  }

  final client = HttpClient();
  client.method = HttpMethod.POST;
  client.endPoint = 'search';
  client.addData('query', searchTerm);

  try {
    final responseStr = await client.execute();
    final response = SearchResponse.fromJson(responseStr);
    _searchStreamController.add(response.data);
  } catch (e) {
    _searchStreamController.addError(e);
  }
}

我想在CircularProgressIndicator每次search(String searchedTerm)调用函数时显示。

谢谢你。

4

3 回答 3

1

你可以试试 :

StreamBuilder<List<Model>>(
          builder: (context, snapshot) {
            switch (snapshot.connectionState) {
              case ConnectionState.none:
                return Center(child: Text('Your results will appear here'));

              case ConnectionState.active:
              case ConnectionState.waiting:
                return Center(child: CircularProgressIndicator());

              case ConnectionState.done:
                if (snapshot.hasError)
                  return Center(child: Text('Error occurred'));

                if (snapshot.data.isEmpty) {
                  return Container(child: Center(child: Text('Found nothing')));
                } else {
                  return ListView.separated(
                    itemCount: snapshot.data.length,
                    separatorBuilder: (context, index) => Divider(height: 1),
                    itemBuilder: (context, index) {
                      final item = snapshot.data[index];
                      return ItemWidget(item);
                    },
                  );
                }
            }
            return Center(child: Text('Your results will appear here'));
          },
        )
于 2020-08-24T13:04:39.397 回答
0

这是我必须做的事情才能达到我的要求。如果有更好的方法来实现这一点,请发布答案,我会将其标记为正确。

哈克

class JugarModel<T> {
  bool isProcessing;
  T data;

  JugarModel({this.isProcessing, this.data});
}

然后使用这个isProcessing属性来检查是否显示CircularProgressIndicatorListView。剩下的代码变成了:

小部件

StreamBuilder<JugarModel>(
  stream: bloc.searchStream,
  builder: (context, snapshot) {

    if (snapshot.hasError) {
      return Center(
        child: Text(
          'Error occurred'
        ),
      );
    }

    if (!snapshot.hasData) {
      return Center(
        child: Text(
          'Your results will appear here'
        ),
      );
    }

    if (snapshot.hasData && snapshot.data.data.isEmpty) {

      if (snapshot.data.isProcessing) {
        return Center(
          child: CircularProgressIndicator(),
        );
      } else {
        return Center(
          child: Text(
            'Found nothing'
          ),
        );
      }
    }

    return ListView.separated(
      itemCount: snapshot.data.data.length,
      separatorBuilder: (context, index) => Divider(height: 1),
      itemBuilder: (context, index) {
        final item = snapshot.data.data[index];
        return ItemWidget(item);
      },
    );
  },
)

集团

final _searchStreamController = StreamController<JugarModel<List<Data>>>();
Stream<JugarModel<List<Data>>> get searchStream => _searchStreamController.stream;

void search(String searchTerm) async {

  if (searchTerm.isEmpty) {
    _searchStreamController.add(null);
    return;
  }

  final client = HttpClient();
  client.method = HttpMethod.POST;
  client.endPoint = 'search';
  client.addData('query', searchTerm);

  // This MAGIC line will call StreamBuilder callback with isProcessing set to true.
  _searchStreamController.add(JugarModel<List<Data>>(isProcessing: true, data: List()));
  try {
    final responseStr = await client.execute();
    final response = SearchResponse.fromJson(responseStr);

    // And after we've received response from API and parsed it, we're calling StreamBuilder
    // callback again with isProcessing set to false.
    _searchStreamController.add(JugarModel<List<Data>>(isProcessing: false, data: response.data));
  } catch (e) {
    _searchStreamController.addError(e);
  }
}
于 2020-08-24T14:23:18.943 回答
0
    StreamBuilder<List<Model>>(
      stream: bloc.searchStream,
      builder: (context, snapshot) {
 
        if (snapshot.hasData) {
         if (snapshot.data.length ==0){ 
              return  Center(
                 child: Text(
                      'Found nothing'
                    ),
              );
    
            } 
        return ListView.separated(
          itemCount: snapshot.data.length,
          separatorBuilder: (context, index) => Divider(height: 1),
          itemBuilder: (context, index) {
            final item = snapshot.data[index];
            return ItemWidget(item);
          },
        );
        }else if (snapshot.hasError) {
          return Center(
            child: Text(
              'Error occurred'
            ),
          );
      }else {
         return Center(
            child:CircularProgressIndicator()
          );
       }
      },
    )

给出一个初始 Text() 小部件,其值为“结果将出现在此处”,然后单击按钮,将初始 Text() 小部件替换为 StreamBuilder

于 2020-08-24T12:40:41.370 回答