簡體   English   中英

Flutter Firestore 從 firestore 讀取數組

[英]Flutter Firestore read an array from firestore

我正在嘗試將 StreamBuilder 與 ListView.builder 結合使用來顯示存儲在 firebase 上的數組中的數據。

我試過使用下面的代碼來訪問數組,但我真的不知道我做錯了什么。

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamBuilder<List<Beacon>>(
        stream: DatabaseService().beacons,
        builder: (context, snapshot) {
          return BeaconList(),
        }
    );
  }
}

class BeaconList extends StatefulWidget {
  @override
  _BeaconListState createState() => _BeaconListState();
}

class _BeaconListState extends State<BeaconList> {
  @override
  Widget build(BuildContext context) {
    final beacons = Provider.of<List<Beacon>>(context) ?? [];

    return ListView.builder(
      itemCount: beacons.length,
      itemBuilder: (context, index) {
        return BeaconTile(beacon: beacons[index]);
      },
    );
  }
}

class BeaconTile extends StatefulWidget {
  final Beacon beacon;
  BeaconTile({this.beacon});
  @override
  _BeaconTileState createState() => _BeaconTileState();
}

class _BeaconTileState extends State<BeaconTile> {
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.only(top: 8),
      child: Card(
        margin: EdgeInsets.fromLTRB(20, 6, 20, 0),
        child: ListTile(
          leading: CircleAvatar(
            radius: 25,
            backgroundColor: widget.beacon.bid Colors.green[400],
          ),
          title: Text("Connection made"),
          subtitle: Text("ID: ${widget.beacon.bid}"),
        ),
      ),
    );
  }
}

class Beacon {
  String bid;
  Beacon({this.bid});
}

final DocumentReference beaconCollection = Firestore.instance.collection("LocationData").document("BeaconData");

List<Beacon> _beaconListFromSnapshot(DocumentSnapshot snapshot) {
  List<Beacon> beaconList = [];
  for (int i = 0; i < snapshot.data.length; i++) {
    print(i);
    beaconList.add(Beacon(bid: snapshot.data[i]));
  }
  return beaconList;
}

Stream<List<Beacon>> get beacons {
  return beaconCollection.get()
      .then((snapshot) {
    try {
      return _beaconListFromSnapshot(snapshot);
    } catch(e) {
      print(e.toString());
      return null;
    }
  }).asStream();
}

運行上面的代碼我得到錯誤:

I/flutter (30206): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (30206): The following ProviderNotFoundException was thrown building BeaconList(dirty, state:
I/flutter (30206): _BeaconListState#6361b):
I/flutter (30206): Error: Could not find the correct Provider<List<Beacon>> above this BeaconList Widget
I/flutter (30206): 
I/flutter (30206): This likely happens because you used a `BuildContext` that does not include the provider
I/flutter (30206): of your choice. There are a few common scenarios:
I/flutter (30206): 
I/flutter (30206): - The provider you are trying to read is in a different route.
I/flutter (30206): 
I/flutter (30206):   Providers are "scoped". So if you insert of provider inside a route, then
I/flutter (30206):   other routes will not be able to access that provider.
I/flutter (30206): 
I/flutter (30206): - You used a `BuildContext` that is an ancestor of the provider you are trying to read.
I/flutter (30206): 
I/flutter (30206):   Make sure that BeaconList is under your MultiProvider/Provider<List<Beacon>>.
I/flutter (30206):   This usually happen when you are creating a provider and trying to read it immediately.
I/flutter (30206): 
I/flutter (30206):   For example, instead of:
I/flutter (30206): 
I/flutter (30206):   ```
I/flutter (30206):   Widget build(BuildContext context) {
I/flutter (30206):     return Provider<Example>(
I/flutter (30206):       create: (_) => Example(),
I/flutter (30206):       // Will throw a ProviderNotFoundError, because `context` is associated
I/flutter (30206):       // to the widget that is the parent of `Provider<Example>`
I/flutter (30206):       child: Text(context.watch<Example>()),
I/flutter (30206):     ),
I/flutter (30206):   }
I/flutter (30206):   ```
I/flutter (30206): 
I/flutter (30206):   consider using `builder` like so:
I/flutter (30206): 
I/flutter (30206):   ```
I/flutter (30206):   Widget build(BuildContext context) {
I/flutter (30206):     return Provider<Example>(
I/flutter (30206):       create: (_) => Example(),
I/flutter (30206):       // we use `builder` to obtain a new `BuildContext` that has access to the provider
I/flutter (30206):       builder: (context) {
I/flutter (30206):         // No longer throws
I/flutter (30206):         return Text(context.watch<Example>()),
I/flutter (30206):       }
I/flutter (30206):     ),
I/flutter (30206):   }
I/flutter (30206):   ```
I/flutter (30206): 
I/flutter (30206): If none of these solutions work, consider asking for help on StackOverflow:
I/flutter (30206): https://stackoverflow.com/questions/tagged/flutter
I/flutter (30206): 
I/flutter (30206): The relevant error-causing widget was:
I/flutter (30206):   BeaconList file:///F:/apps/rivi_mvp/lib/screens/home/home.dart:43:19
I/flutter (30206): 

我嘗試了很多不同的東西,但我認為我對 StreamBuilders 和 Providers 以及流的了解不足以找到解決方案。 任何解決方案或見解將不勝感激。

因此,在搞砸了 2 天之后,我找到了一個適合我的解決方案。

通過用StreamProvider<List<Beacon>>.value替換StreamBuilder ,這允許我使用 BeaconList 小部件樹適當地訪問數據

final beacons = Provider.of<List<Beacon>>(context) ?? []; .

就實際流而言 - 我在 Firestore 中有數據在代碼中被編寫為

{Beacons: [{bid: "1234",}, {bid: "2345",}, {bid: "3456",}]}

所以對於流的代碼,為了格式化我使用的數據

List<Beacon> _beaconListFromSnapshot(QuerySnapshot snapshot) {
    List<Beacon> x = [];
    return snapshot.documents.map((doc) {
      for (Map data in doc.data["Beacons"]) {
        x.add(Beacon(bid: data["bid"],));
      }
      return x;
    }).toList()[0];
  }

  Stream<List<Beacon>> get brews {
    return beaconCollection.snapshots().map(_beaconListFromSnapshot);
  }

如果有人能提出一個更有效或更雄辯的解決方案或指向一個解決方案,那么我將不勝感激。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM