Null error on loading image from php in card swiper

Viewed 72

This is the home page function in which I added an image slider(card swiper) for the carousel image and the images are loaded from the PHP network but the images aren't able to load and throw the null error and also its body is loaded in next function the code is below:

  class Home extends StatefulWidget {
    Home({
    Key? key,
    required this.body,
    }) : super(key: key);
    final body;

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

    class _HomeState extends State<Home> {
    Future<List<ModelEbook>>? getSlider;
    List<ModelEbook> listSlider = [];

    @override
    void initState() {
    super.initState();
    getSlider = fetchEbook(listSlider);
    }

    @override
    Widget build(BuildContext context) {
    return Container(
      child: SingleChildScrollView(
        child: FutureBuilder(
          future: getSlider,
          builder:
              (BuildContext context, AsyncSnapshot<List<ModelEbook>> snapshot) {
            if (snapshot.connectionState == ConnectionState.done) {
              //displays data here
              return Column(
                children: [
                  //Slider
                  // ImageSlider(),
                  Container(
                    child: FutureBuilder(
                      future: getSlider,
                      builder: (BuildContext context,
                          AsyncSnapshot<List<ModelEbook>> snapshot) {
                        if (snapshot.connectionState == ConnectionState.done) {
                          //Create design in here

                          return SizedBox(
                            height: 27.0.h,
                            child: Swiper(
                              autoplay: true,
                              itemCount: snapshot.data!.length,
                              itemBuilder: (BuildContext context, int index) {
                                // ModelEbook _ = snapshot.data![index];
                                return GestureDetector(
                                  onTap: () {},
                                  child: Padding(
                                    padding: EdgeInsets.all(10),
                                    child: Container(
                                      child: Stack(
                                        children: [
                                          ClipRRect(
                                            child: Image.network(
                                              listSlider[index].photo,
                                              fit: BoxFit.cover,
                                              width: 100.0.w,
                                            ),
                                            borderRadius:
                                                BorderRadius.circular(15),
                                          ),
                                        ],
                                      ),
                                    ),
                                  ),
                                );
                              },
                            ),
                          );
                        } else {
                          return Container();
                        }
                      },
                    ),
                  ),


                ],
              );
            } else if (snapshot.connectionState == ConnectionState.waiting) {
              return Center(child: CircularProgressIndicator());
            } else {
              print('error');
              return Text('error');
            }
          },
        ),
      ),
    );

this is the body of the above function in which I also added a customized app bar and bottom navigation bar:

 class _HomeScreenState extends State<HomeScreen> {
     bool _folded = true;

     get currentIndex => null;

     @override
    Widget build(BuildContext context) {
      return Scaffold(
      body: AnimatedContainer(
        duration: Duration(milliseconds: 250),
        color: Colors.blueGrey.shade100,
        child: Column(
          children: [
            Row(
               mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                IconButton(
                  icon: SvgPicture.asset(
                    "assets/icons/menu.svg",
                  ),
                  onPressed: () {},
                ),
                Padding(
                  padding: const EdgeInsets.only(left: 110),
                  child: Container(
                    width: _folded ? 52 : 250,
                    height: getProportionateScreenHeight(50),
                    decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(32),
                        color: Colors.white,
                        boxShadow: [
                          BoxShadow(
                            color: Colors.brown.shade300.withOpacity(0.3),
                            spreadRadius: 0,
                            blurRadius: 8,
                            offset: Offset(-4, 0),
                          ),
                          BoxShadow(
                            color: Colors.grey.withOpacity(0.3),
                            spreadRadius: 0,
                            blurRadius: 8,
                            offset: Offset(4, 0),
                          ),
                          BoxShadow(
                            color: Colors.brown.shade300.withOpacity(0.3),
                            spreadRadius: 0,
                            blurRadius: 8,
                            offset: Offset(-4, 0),
                          ),
                          BoxShadow(
                            color: Colors.grey.withOpacity(0.3),
                            spreadRadius: 0,
                            blurRadius: 8,
                            offset: Offset(4, 0),
                          ),
                        ]),
                    child: Row(
                      children: [
                        Expanded(
                          child: Container(
                            padding: EdgeInsets.only(left: 16),
                            child: !_folded
                                ? TextField(
                                    decoration: InputDecoration(
                                      hintText: 'Search Book, Author,Genre ',
                                      hintStyle: TextStyle(
                                        color: Colors.black54,
                                        fontFamily:
                                            GoogleFonts.oregano().fontFamily,
                                      ),
                                      border: InputBorder.none,
                                    ),
                                  )
                                : null,
                          ),
                        ),
                        AnimatedContainer(
                          duration: Duration(milliseconds: 400),
                          child: Material(
                            type: MaterialType.transparency,
                            child: InkWell(
                                borderRadius: BorderRadius.only(
                                  topLeft: Radius.circular(_folded ? 32 : 0),
                                  topRight: Radius.circular(32),
                                  bottomLeft: Radius.circular(_folded ? 32 : 0),
                                  bottomRight: Radius.circular(32),
                                ),
                                child: Padding(
                                  padding: const EdgeInsets.all(16.0),
                                  child: SvgPicture.asset(
                                      _folded
                                          ? "assets/icons/search.svg"
                                          : "assets/icons/close.svg",
                                      height: getProportionateScreenHeight(18),
                                      color: Colors.black54),
                                ),
                                onTap: () {
                                  setState(() {
                                    _folded = !_folded;
                                  });
                                }),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
            
            Expanded(
              child: Home(
                body: currentIndex,
              ),
            ),
            Expanded(
              child: BottomDrawer(),
            ),
          
          ],
        ),
      ),
    );
  }
}

and this is the error shown after running the above command enter image description here

and this is the error shown on the emulator after running the above command

enter image description here

Future<List<ModelEbook>> fetchEbook(List<ModelEbook> fetch) async 
    {
    print(
      "baseUrl ${ApiConstant().baseUrl + ApiConstant().api + 
    ApiConstant().latest}");
     var request = await Dio()
      .get(ApiConstant().baseUrl + ApiConstant().api + 
    ApiConstant().latest);

    for (Map<String, dynamic> ebook in request.data) {
    fetch.add(
      ModelEbook(
        id: ebook['id'],
        title: ebook['title'],
        photo: ebook['photo'],
        description: ebook['description'],
        catId: ebook['cat_id'],
        statusNews: ebook['status_newsNews'],
        pdf: ebook['pdf'],
        date: ebook['date'],
        authorName: ebook['author_name'],
        publisherName: ebook['publisher_name'],
        pages: ebook['pages'],
        language: ebook['language'],
        rating: ebook['rating'],
        free: ebook['free'], 
      ),
    );
    print("checkEbookFromDB ${ebook['photo']}");
    }
    return fetch;
    }

    class ApiConstant {
  String baseUrl = "http://i.p address(here)/ebookapp/";
  String api = "api.php?";
  String slider = "slider";
  String latest = "latest";

1 Answers

You don't need to call twice API to get the same data, use parent snapshot for inner child and follow FutureBuilder structure. Calling future initState doesn't provide data in this case, you can create another async method to handle it, but this will be simple, don't need to use initState

class _HomeState extends State<Home> {
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: SingleChildScrollView(
        child: FutureBuilder(
          future: fetchEbook(),
          builder:
              (BuildContext context, AsyncSnapshot<List<ModelEbook>> snapshot) {
            if (snapshot.connectionState == ConnectionState.done &&
                snapshot.hasData) {
              //displays data here
              return Column(
                children: [
                  //Slider
                  // ImageSlider(),
                  Container(
                    child: SizedBox(
                      height: 27.0.h,
                      child: Swiper(
                        autoplay: true,
                        itemCount: snapshot.data!.length,
                        itemBuilder: (BuildContext context, int index) {
                          // ModelEbook _ = snapshot.data![index];
                          return GestureDetector(
                            onTap: () {},
                            child: Padding(
                              padding: EdgeInsets.all(10),
                              child: Container(
                                child: Stack(
                                  children: [
                                    ClipRRect(
                                      child: Image.network(
                                        snapshot.data![index].photo,
                                        fit: BoxFit.cover,
                                        width: 100.0.w,
                                      ),
                                      borderRadius: BorderRadius.circular(15),
                                    ),
                                  ],
                                ),
                              ),
                            ),
                          );
                        },
                      ),
                    ),
                  ),
                ],
              );
            } else if (snapshot.connectionState == ConnectionState.waiting) {
              return Center(child: CircularProgressIndicator());
            } else {
              print('error');
              return Text('error');
            }
          },
        ),
      ),
    );
  }
}

It is better to return nullable list from fetchEbook because of uncertain future. More about FutureBuilder

Related