How to make a reusuable Futurebuilder

149

You can write a generic widget similar to this one:

class DealsWidget<T> extends StatelessWidget {
  final Future<T> future;
  final String category;
  final IconData iconData;
  final Color color;
  final String loadingText;

  DealsWidget({
    this.future,
    this.category,
    this.iconData,
    this.color,
    this.loadingText,
  });

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<T>(
      future: future,
      builder: (context, AsyncSnapshot<T> snapshot) {
        if (snapshot.hasData) {
          return RowBoxes(
            categoryName: category,
            icon: Icon(
              iconData,
              color: color,
            ),
          );
        }
        return Text(loadingText);
      },
    );
  }
}

And use it like:

DealsWidget<Product>(
   future: readAllProducts(),
   category: 'Weekly Deals',
   iconData: Icons.arrow_forward,
   color: Colors.orange,
   loadingText: 'Please Wait...'
)
Share:
149
IcyHerrscher
Author by

IcyHerrscher

Updated on December 31, 2022

Comments

  • IcyHerrscher
    IcyHerrscher over 1 year

    I have to build multiple future builders for different types of categories for a screen, like: Weekly deal, All, Newly Arrived, etc. My codes right now is pretty barebone, but here it is.

    +Home Screen

    import 'package:flutter/material.dart';
    import 'package:http/http.dart';
    import 'package:vgo_customer_side/models/Product.dart';
    import 'package:vgo_customer_side/repos/ProductRepo.dart';
    import 'package:vgo_customer_side/widgets/Boxes.dart';
    import 'package:vgo_customer_side/widgets/MyFunction.dart';
    
    
    class GeneralScreen extends StatefulWidget {
      const GeneralScreen({Key? key}) : super(key: key);
    
      @override
      _GeneralScreenState createState() => _GeneralScreenState();
    }
    
    class _GeneralScreenState extends State<GeneralScreen> with AutomaticKeepAliveClientMixin<GeneralScreen> {
      List list = ["Weekly Deal", "Relevant", "Freshly"];
      late Future<Product> futureProduct;
    
      @override
      void initState(){
        futureProduct = readAllProducts();
        super.initState();
      }
      String? rise;
    
      @override
      // TODO: implement wantKeepAlive
      bool get wantKeepAlive => true;
    
      @override
      Widget build(BuildContext context) {
        super.build(context);
        return Container(
          constraints: BoxConstraints.tightForFinite(),
          child: SingleChildScrollView(
            child: Column(
              children: [
                deliverField(),
                SizedBox(height: 29,),
                
                
                FutureBuilder<Product>(
                    future: readAllProducts(),
                    builder: (context, AsyncSnapshot<Product> snapshot){
                      if(snapshot.hasData){
                        return RowBoxes(categoryName: "Weekly Deal", icon: Icon(Icons.arrow_forward, color: Colors.orange,));
                      }
                      return Text("waiting");
                    }),
                
                
                SizedBox(height: 10,),
              ElevatedButton(onPressed: (){
                setState(() {
                  futureProduct = readAllProducts();
                });
              }, child: Text("press me")),
              Center(child: Text("All")),
              Center(child: Text("Just for you")),
              _justForYou(),
    
            ],),
          ),
        );
      }
      _justForYou(){
        return Container();
    
      }
      _bottomGrid(){
        return Container();
      }
    } 
    

    +RepoProduct

    import 'package:vgo_customer_side/models/ApiRespone.dart';
    import 'package:vgo_customer_side/models/Product.dart';
    import 'package:http/http.dart' as http;
    
    Future<Product> readAllProducts() async{
      final response = await http.get(Uri.parse('https://vgo-buyer.herokuapp.com/api/v1/shopping/products/'));
      if(response.statusCode == 200){
        for(dynamic data in getAllProductsResponseFromJson(response.body).payload) {
          return Product.fromJson(data);
        }
        throw Exception("Failed to load Products");
      }
      else{
        throw Exception("Failed to load Products");
      }
    }
    

    Now, having to add each "Weekly deal, All, Newly Arrived" to a futurebuilder is a lot of boilerplates, and I would like to simplify it into a reusable widget instead. Like I do with RowBoxes().

    I know how to make normal reusable widgets but when it comes to a futurebuilder, it requires generic type(for the futurebuilder widget) and specific class for its "future:" function. Can anyone show me how to do it?

    • Midhun MP
      Midhun MP almost 3 years
      What you mean by re-usable future builder? Could you please elaborate a little more?
    • IcyHerrscher
      IcyHerrscher almost 3 years
      I have edited my questions. Thanks for checking it out. Do tell if it's still not clear.
    • Midhun MP
      Midhun MP almost 3 years
      Is it possible for you to add current future builder implementation, which you are planning to make it into a separate re-usable component?
    • OMi Shah
      OMi Shah almost 3 years
      You can check this for some ideas medium.com/flutter-community/…
    • IcyHerrscher
      IcyHerrscher almost 3 years
      @Midhun MP Yes, it was what I wasplanning to, but futurebuilder require a generic type which I have no idea how to pass it in a parameter.