Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

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

firebase - Flutter Strean builder runs initialay and show error The getter 'length' was called on null.but after gesturedetector clicks it runs correctly

1.This is the first page i need to run This code runs initially and give The 'length' was called on null. Receiver: null Tried calling: length Type error but after clicks gesture it runs perfectly i need run this code before gesture detector calls I tried without gesture detector but it not works.

class ProductPage extends StatefulWidget {

  @override
  _ProductPageState createState() => _ProductPageState();
}

class _ProductPageState extends State<ProductPage> {

  String id=' RN62p5KZAtk48mGL2n66';
  int selectedIndex = 0;
  String district;
  bool loading = false;


  _ProductPageState();
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            SizedBox(height: 30.0,),
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 20.0),
              child: SizedBox(
                height: 25,
                child:StreamBuilder<List<CategoryModel>>(
                  stream: DatabaseService().getCategories(),
                  builder: (context, snapshot) {
                    return ListView.builder(
                        itemCount: snapshot.data.length,
                        scrollDirection: Axis.horizontal,
                        itemBuilder: (context, index) => buildCategory(
                            index,
                            snapshot.data[index].categoryName,
                            snapshot.data[index].id
                        )
                    );

                  },
                ),
              ),
            ),

            StreamBuilder<QuerySnapshot>(
                stream: FirebaseFirestore.instance.collection('district').snapshots(),
                builder: (context, snapshot) {

                  return Container(
                    padding: EdgeInsets.only(bottom: 16.0),
                    child: Row(
                      children: <Widget>[
                        Expanded(
                            flex: 2,
                            child: Container(
                              padding: EdgeInsets.fromLTRB(12.0, 10.0, 10.0, 10.0),
                              child: Text(
                                "District",
                              ),
                            )),
                        new Expanded(
                          flex: 4,
                          child: DropdownButton(
                            value: district,

                            isDense: true,
                            onChanged: (valueSelectedByUser) {
                              setState(() {
                                this.district = valueSelectedByUser;
                              });

                              print(district);

                            },
                            hint: Text('Sort By District'),
                            items: snapshot.data.docs
                                .map((DocumentSnapshot document) {
                              return DropdownMenuItem<String>(
                                value: document.data()['Name'],

                                child: Text(document.data()['Name'] ),
                              );
                            }).toList(),
                          ),
                        ),
                      ],
                    ),
                  );
                }),
            district  == null ?  Expanded(
             flex: 1,
             child: StreamBuilder<List<SubCategoryModel>>(
               stream:DatabaseService().getSubCategories(id),
               builder: (context,snapshot){
                 if(!snapshot.hasData){
                   return Center(
                     child: CircularProgressIndicator(),
                   );
                 }else {
                   return ListView.builder(
                       itemCount: snapshot.data.length,
                       itemBuilder: (context, index) {
                         return PostContainer(
                           id: snapshot.data[index].listId,
                           likes: snapshot.data[index].likes,
                           views: snapshot.data[index].views,
                           imageUrl: snapshot.data[index].imageUrl,
                           longitude: snapshot.data[index].longitude,
                           latitude: snapshot.data[index].latitude,
                           providerName: snapshot.data[index].providerName,
                           providerTel: snapshot.data[index].providerTel,
                           units: snapshot.data[index].units,
                           description: snapshot.data[index].description,
                           unitPrice: snapshot.data[index].unitPrice,
                           name: snapshot.data[index].name,
                           date: snapshot.data[index].date,
                           providerId: snapshot.data[index].providerId,
                           categoryId: snapshot.data[index].categoryId,
                           providerImage: snapshot.data[index].providerImage,
                           district: snapshot.data[index].district,
                           address: snapshot.data[index].address,

                         );
                       }
                   );
                 }
               },
             ),
           ):
           Expanded(
             flex: 1,
             child: StreamBuilder<List<SubCategoryModel>>(
               stream: DatabaseService().getSortedSubCategories(id, district),
               builder: (context,snapshot){
                    if(!snapshot.hasData){
                    return Center(
                    child: CircularProgressIndicator(),
                    );
                    }else {
                      return ListView.builder(
                          itemCount: snapshot.data.length,
                          itemBuilder: (context, index) {
                            return PostContainer(
                              id: snapshot.data[index].listId,
                              likes: snapshot.data[index].likes,
                              views: snapshot.data[index].views,
                              imageUrl: snapshot.data[index].imageUrl,
                              longitude: snapshot.data[index].longitude,
                              latitude: snapshot.data[index].latitude,
                              providerName: snapshot.data[index].providerName,
                              providerTel: snapshot.data[index].providerTel,
                              units: snapshot.data[index].units,
                              description: snapshot.data[index].description,
                              unitPrice: snapshot.data[index].unitPrice,
                              name: snapshot.data[index].name,
                              date: snapshot.data[index].date,
                              providerId: snapshot.data[index].providerId,
                              categoryId: snapshot.data[index].categoryId,
                              providerImage: snapshot.data[index]
                                  .providerImage,
                              district: snapshot.data[index].district,
                              address: snapshot.data[index].address,

                            );
                          }
                      );
                    }
               },
             ),
           ),

          ],
        )

    );

  }

  Widget buildCategory(int index,String categoryName,String catId) {
    return GestureDetector(
      onTap: () {
        setState(() {
          selectedIndex = index;
          id= catId;
        });
      },
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 20),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text(
              categoryName,
              style: TextStyle(
                fontWeight: FontWeight.bold,
                color: selectedIndex == index ?  Color(0xFF535353) : Color(0xFF535353),
              ),
            ),
            Container(
              margin: EdgeInsets.only(top: 20 / 4), //top padding 5
              height: 2,
              width: 30,
              color: selectedIndex == index ? Colors.black : Colors.transparent,
            )
          ],
        ),
      ),
    );
  }
  Future<void> _shoeerror() async {
    return showDialog<void>(
      context: context,
      barrierDismissible: false, // user must tap button!
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text('Thank you For Join with Us !'),
          content: SingleChildScrollView(
            child: ListBody(
              children: <Widget>[
                Row(
                  children: [

                    Text('Select the Category to proceed '),
         
                  ],
                )


              ],
            ),
          ),
          actions: <Widget>[
            TextButton(
              child: Text('OK'),
              onPressed: () {
                setState(() {
                  id=' RN62p5KZAtk48mGL2n66';
                });
              },
            ),
          ],
        );
      },
    );
  }
}

2.this is the database call function

  Stream<List<SubCategoryModel>> getSubCategories(docId) {
    return _db.collection('categories').doc(docId).collection('subCategories').snapshots().map((snapshot) =>
        snapshot.docs.map((doc) => SubCategoryModel.fromJson(doc.data())).toList());
  }

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

1 Reply

0 votes
by (71.8m points)

I suspect this is being executed on each build with a side effect... perhaps recreating the stream back to its initial state:

stream: DatabaseService().getCategories()

For the "Builder" widgets expecting a future or a stream, you need to create what they are watching as a value outside the build() method... perhaps in an initState, or my favorite, in a Riverpod provider.

Also, you don't seem to have any conditional based on the non-null value of snapshot.data, so it will blow up because of .length. This is expected behavior. :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

56.8k users

...