Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
267 views
in Technique[技术] by (71.8m points)

flutter - Creating a Stream from a List to Build Cards


I'm creating a Home Auto Application. I have several button datas stored inside my Database (Realtime Database). In my home page I created a StreamBuilder to listen to whenever there is a button created or any type of data that has entered or leaved.

I'm currently having problems with my StreamBuilder, I can't access the data from it on the main page, and when I try to print the snapshot.data, I get 0 as response. The Stream is a List.

This is the output from snapshot.value:

[{icon: delte, nome: Junior}, {icon: add, nome: Televisao}, {icon: bulb, nome: BAtata}]

This is the Stream:

Stream<List> readData() async*{
    Map<dynamic, dynamic> button_list = Map();
    var lst = [];

    final FirebaseUser user = await _auth.currentUser();

    Stream stream = await databaseReference.child(user.uid+"/buttons/").once().then((DataSnapshot snapshot) {
      final value = snapshot.value as Map;
      lst = value.values.toList();
      
    });

    await for(var event in stream) {
      yield event.lst;
    }
  }

I will be using the content from the list to create the buttons.
This is the create card page:

import 'package:flutter/material.dart';

class CreateCard extends StatelessWidget {

  String name;
  String icon;
  CreateCard(this.name, [this.icon]); //[] para que o icon n?o seja obrigatorio de colocar

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: (){
        
      },
      child: Container(
        width: 150,
        height: 150,
        decoration: BoxDecoration(
          color: Colors.black,
          borderRadius: BorderRadius.circular(15)
        ),
        child: Stack(
          children: [
            Positioned(
              top: 10,
              left: 10,
              child: Icon(
                icon == null ? Icons.check_box_outline_blank : getIconData(icon),
                size: 35,
                color: Colors.white,
              ),
            ),
            Positioned(
              top: 95,
              left: 15,
              child: Text(name, style: TextStyle(color: Colors.white),),
            ),
          ],
        ),
      ),
    );
  }
}

IconData getIconData(String name) {
  switch (name) {
    case "Lock":
      return Icons.lock;
    case "LightBulb":
      return Icons.lightbulb_outline;
    case "Check":
      return Icons.check;
  }
}

This is the Home Screen:

import 'package:automacaoaplicativo/buttons/create_card.dart';
import 'package:flutter/material.dart';
import 'package:automacaoaplicativo/services/auth.dart';

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {

  final AuthService _auth = AuthService();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey,
      appBar: AppBar(
        title: Text('Main page'),
        actions: <Widget>[
          FlatButton.icon(onPressed: () {
            _auth.signOut();
          }, 
          icon: Icon(Icons.logout), 
          label: Text('Logout'))
        ],
      ),
      body: StreamBuilder(
        stream: _auth.readData(),
        initialData: 0,
        builder: (context, snapshot) {
          if (snapshot.hasError || snapshot.hasError){
            return Container(color: Colors.red);
          }
          if (!snapshot.hasData || !snapshot.hasData){
            return Center(child: CircularProgressIndicator());
          }
          if (snapshot.hasData || snapshot.hasData){
            return GridView.count(
              padding: EdgeInsets.all(15),
              crossAxisSpacing: 20.0,
              mainAxisSpacing: 20.0,
              crossAxisCount: 3,
              children: [
                CreateCard("ola"), // I would need to loop throw this card and 
send the data from readData() on the list format,
 CreateCard(snapshot.data[0][0], snapshot.data[0][1]) and so on for position 1, 2, etc
                GestureDetector(
                  onTap: () async{
                    _auth.readData();
                  },
                    child: Container(
                    color: Colors.black,
                    width: 150,
                    height: 150,
                    child: Icon(Icons.add, color: Colors.white,),
                    
                  ),
                ),
              ],
            );
          }
        }
      ),
    );
  }
}

This is how the app is looking, there was supposed to be 3 of these black boxes since I have 3 data from buttons, If I had 4 there was supposed to be 4, and so on: App

question from:https://stackoverflow.com/questions/65848670/creating-a-stream-from-a-list-to-build-cards

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You should try matching your stream design pattern to something like this:

void main() async {
  // This is where you would use a StreamBuilder rather than this use.
  await for (var value in getData()) {
    print(value);
  }
  
  /*
   * return StreamBuilder<List>(
   *  stream: getData(),
   *  builder: (context, snapshot) => YourWidget(snapshot.data);
   * );
   * */
}

// This is *your* Stream function.
Stream<List> getData() async* {
  var list = [];

  // Make sure the stream you are wrapping is invokable.
  await for (var data in mockRemoteData(10)) {
    // this is where you do you data manipulation.

    list.add(data);
    yield list;
  }
}

// Ignore the implmentation, just imagine you are recieving data from a network
// and it just timeouts at some point.
Stream<int> mockRemoteData(int timeout) async* {
  int i = 0;
  while (true) {
    await Future.delayed(const Duration(seconds: 1));
    yield i++;
    if (i == timeout) break;
  }
}

getData() is the function you are trying to make. You are basically wrapping another Stream, in the example it is mockRemoteData(). Try matching your code to this pattern.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...