Stream for API coming from PHP in Flutter (Not Firebase)
Asked Answered
H

3

9

Let's say I have an API - example: https://jsonplaceholder.typicode.com/posts

Now, I want to apply StreamBuilder to it with a ListView have ListTiles. How do I configure? How do I create a stream for it?

I totally understood the firebase and firestore stream. I want to understand if I have an API coming from PHP and I want to build a StreamBuilder, how do I do it.

Henze answered 19/8, 2019 at 10:12 Comment(2)
I am actually lost in this Stream type. I wanted to create a List View with a url. The first requirement was to create a Stream for StreamBuilder. Rest of the snapshots and builders are understandable. Only Not sure about how to create a Stream. In most of the areas, all have user stream for firestore and i want to know if i have my own database and Api coming from PHP, how do i create a Stream.Henze
check this gist.github.com/bobykurniawan11/…, hope can help youRodger
H
12

Please reference this doc https://blog.khophi.co/using-refreshindicator-with-flutter-streambuilder/

There is also a video in it

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

full example code

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');
          }
        },
      ),
    );
  }
}

your json class in PHP

// 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,
    };
}
Hau answered 20/8, 2019 at 1:2 Comment(0)
E
9

After a lot of research, I tried to solve mine with this code below This code solve Live Data from 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('[email protected]', '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('[email protected]', '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();
  }
}
Erich answered 16/10, 2019 at 13:41 Comment(0)
B
0

tis works for me

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(),
);
}
}
Began answered 2/2, 2022 at 6:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.