7

假设我有一个 API - 例如:https ://jsonplaceholder.typicode.com/posts

现在,我想将 StreamBuilder 应用到具有 ListView 的 ListTiles 上。我该如何配置?如何为其创建流?

我完全理解了 firebase 和 firestore 流。我想了解我是否有一个来自 PHP 的 API,并且我想构建一个 StreamBuilder,我该怎么做。

4

3 回答 3

11

请参考此文档https://blog.khophi.co/using-refreshindicator-with-flutter-streambuilder/

里面还有一段视频

github 代码https://github.com/seanmavley/refreshindicator-with-streambuilder/blob/master/lib/main.dart

完整的示例代码

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:async';
import 'dart:convert';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Basic Project',
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  StreamController _postsController;
  final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>();

  int count = 1;

  Future fetchPost([howMany = 5]) async {
    final response = await http.get(
        'https://blog.khophi.co/wp-json/wp/v2/posts/?per_page=$howMany&context=embed');

    if (response.statusCode == 200) {
      return json.decode(response.body);
    } else {
      throw Exception('Failed to load post');
    }
  }

  loadPosts() async {
    fetchPost().then((res) async {
      _postsController.add(res);
      return res;
    });
  }

  showSnack() {
    return scaffoldKey.currentState.showSnackBar(
      SnackBar(
        content: Text('New content loaded'),
      ),
    );
  }

  Future<Null> _handleRefresh() async {
    count++;
    print(count);
    fetchPost(count * 5).then((res) async {
      _postsController.add(res);
      showSnack();
      return null;
    });
  }

  @override
  void initState() {
    _postsController = new StreamController();
    loadPosts();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      key: scaffoldKey,
      appBar: new AppBar(
        title: new Text('StreamBuilder'),
        actions: <Widget>[
          IconButton(
            tooltip: 'Refresh',
            icon: Icon(Icons.refresh),
            onPressed: _handleRefresh,
          )
        ],
      ),
      body: StreamBuilder(
        stream: _postsController.stream,
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          print('Has error: ${snapshot.hasError}');
          print('Has data: ${snapshot.hasData}');
          print('Snapshot Data ${snapshot.data}');

          if (snapshot.hasError) {
            return Text(snapshot.error);
          }

          if (snapshot.hasData) {
            return Column(
              children: <Widget>[
                Expanded(
                  child: Scrollbar(
                    child: RefreshIndicator(
                      onRefresh: _handleRefresh,
                      child: ListView.builder(
                        physics: const AlwaysScrollableScrollPhysics(),
                        itemCount: snapshot.data.length,
                        itemBuilder: (context, index) {
                          var post = snapshot.data[index];
                          return ListTile(
                            title: Text(post['title']['rendered']),
                            subtitle: Text(post['date']),
                          );
                        },
                      ),
                    ),
                  ),
                ),
              ],
            );
          }

          if (snapshot.connectionState != ConnectionState.done) {
            return Center(
              child: CircularProgressIndicator(),
            );
          }

          if (!snapshot.hasData &&
              snapshot.connectionState == ConnectionState.done) {
            return Text('No Posts');
          }
        },
      ),
    );
  }
}

你在 PHP 中的 json 类

// To parse this JSON data, do
//
//     final payload = payloadFromJson(jsonString);

import 'dart:convert';

List<Payload> payloadFromJson(String str) => new List<Payload>.from(json.decode(str).map((x) => Payload.fromJson(x)));

String payloadToJson(List<Payload> data) => json.encode(new List<dynamic>.from(data.map((x) => x.toJson())));

class Payload {
    int userId;
    int id;
    String title;
    String body;

    Payload({
        this.userId,
        this.id,
        this.title,
        this.body,
    });

    factory Payload.fromJson(Map<String, dynamic> json) => new Payload(
        userId: json["userId"],
        id: json["id"],
        title: json["title"],
        body: json["body"],
    );

    Map<String, dynamic> toJson() => {
        "userId": userId,
        "id": id,
        "title": title,
        "body": body,
    };
}
于 2019-08-20T01:02:18.293 回答
8

经过大量研究,我尝试用下面的代码解决我的问题 此 代码从 API 解决实时数据

import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:live_data_stream/provider/Api.dart';
import 'package:live_data_stream/provider/model/AuthModel.dart';

class DetailsView extends StatefulWidget {
  @override
  _DetailsViewState createState() => _DetailsViewState();
}

class _DetailsViewState extends State<DetailsView> {
  StreamController<AuthModel> _userController;
  final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: scaffoldKey,
      appBar: new AppBar(
        title: new Text('StreamBuilder Demo'),
        actions: <Widget>[
          IconButton(
            tooltip: 'Refresh',
            icon: Icon(Icons.refresh),
            onPressed: _handleRefresh,
          )
        ],
      ),
      body: StreamBuilder(
        stream: _userController.stream,
        builder: (BuildContext context, AsyncSnapshot<AuthModel> snapshot) {
         switch(snapshot.connectionState){
           case ConnectionState.none:
             return Center(
               child: Text('None'),
             );
             break;
           case ConnectionState.waiting:
             return Center(
               child: CircularProgressIndicator(),
             );
             break;
           case ConnectionState.active:
             return Center(
               child:  Text(
                 snapshot.data.fname == null ? 'Null' : snapshot.data.fname,
                 style: Theme.of(context).textTheme.display1,
               ),
             );
             break;
           case ConnectionState.done:
             print('Done is fucking here ${snapshot.data}');
             if(snapshot.hasData){
               return Center(
                 child:  Text(
                   snapshot.data.fname == null ? 'Null' : snapshot.data.fname,
                   style: Theme.of(context).textTheme.display1,
                 ),
               );
             }else if(snapshot.hasError){
               return Text('Has Error');
             }else{
               return Text('Error');
             }
             break;
         }
         return Text('Non in Switch');
        },
      ),
    );
  }
  @override
  void initState() {
    _userController = new StreamController();
    Timer.periodic(Duration(seconds: 1), (_) => loadDetails());
   // loadDetails();
    super.initState();
  }
  int count = 1;

  loadDetails() async {
    Api().getUserInfo('horlaz229@gmail.com', '123456').then((res) async{
      print('LoadDetails of ${res.fname}');
      _userController.add(res);
      return res;
    });
  }

  showSnack() {
    return scaffoldKey.currentState.showSnackBar(
      SnackBar(
        content: Text('New content loaded'),
      ),
    );
  }

  Future<Null> _handleRefresh() async {
    count++;
    print(count);
    Api().getUserInfo('horlaz229@gmail.com', 'APP-1571216683-766').then((res) async {
      print('New Data of ${res.fname}');
      _userController.add(res);
      showSnack();
      return null;
    });
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    _userController.close();
  }
}
于 2019-10-16T13:41:22.837 回答
0

对我有用

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

class PeriodicRequester extends StatelessWidget {
Stream<http.Response> getRandomNumberFact() async* {
yield* Stream.periodic(Duration(seconds: 5), (_) {
  return http.get("http://numbersapi.com/random/");
}).asyncMap((event) async => await event);
}

@override
Widget build(BuildContext context) {
return StreamBuilder<http.Response>(
  stream: getRandomNumberFact(),
  builder: (context, snapshot) => snapshot.hasData
      ? Center(child: Text(snapshot.data.body))
      : CircularProgressIndicator(),
);
}
}
于 2022-02-02T06:11:10.950 回答