Flutter product listing and details using Firestore

1.5k views Asked by At

I'm struggling to get definitive answer to this problem I'm having. I have two screens as show below product listing and product details.

enter image description here

First screen displays list of products (Firebase documents) and when you click on an item it takes you to the product details screen. On product display screen you can mark the product as Favorite and has navigation button to previous and next product.

My question is I don't know what I should use Future or Stream to achieve this.

Problem using Future If I use Future<List<Product>> I cannot maintain bookmark status of a product unless I refresh the product lists every time I bookmark a product. For example if say I have bookmarked product 2 then navigate to product 3 then back to product 2 the bookmark status is not maintained.

Problem using Stream it solves the problem of maintaining bookmarks status but then I don't know how to manage the navigation between products (prev/next)

I have the following code to navigate to next product using Stream

class SearchResultsBloc implements BlocBase {
  SearchResultsBloc() {
    DatabaseService().Search().listen((data) => _inList.add(data));
  }

  final _listController = BehaviorSubject<List<Product>>();
  Stream<List<Product>> get outList => _listController.stream;
  Sink<List<Product>> get _inList => _listController.sink;

 Stream<Product> outDetails(String uid) {
    return outList.map<Product>((results) => results
        .firstWhere((product) => product.uid == uid, orElse: () => null));
  }

}

This method below to retrieves the next product but someone advised that I should not be doing this as the stream could change and also I don't know how I can disable < Prev navigation button if I'm viewing the first product or disable Next > if I'm viewing the last product.

 Stream<Product> nextProduct(String uid) {
    var index = outList
        .map<int>(
            (results) => results.indexWhere((product) => product.uid == uid))
        .first
        .asStream();

    int nextIndex;
    index.listen((index) {
      nextIndex = index + 1;
    });

    return outList.map<Product>((results) => results.elementAt(nextIndex));
  }
1

There are 1 answers

1
Abhishek Ghaskata On

Use StreamBuilder for real-time changes

StreamBuilder<QuerySnapshot>(
      stream:  FirebaseFirestore.instance.collection(Your collection).snapshots(),
      builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
        if (snapshot.hasError) {
          return Text('Something went wrong');
        }

        if (snapshot.connectionState == ConnectionState.waiting) {
          return Text("Loading");
        }

        return new ListView(
          children: snapshot.data.documents.map((DocumentSnapshot document) {
            return new ListTile(
              title: new Text(document.data()[key]),
              subtitle: new Text(document.data()[key]),
            );
          }).toList(),
        );
      },
    );

While navigating to the next page, you have to pass snapshot.data so if there are any changes from the backend, it will affect the UI automatically.

Your outDetails method seems ok, but you just have to pass snapshot.data.document.data() when the user onTap on a particular listTile or your custom widget