IcyHerrscher
IcyHerrscher

Reputation: 486

How to make a reusuable Futurebuilder

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?

Upvotes: 4

Views: 653

Answers (1)

Midhun MP
Midhun MP

Reputation: 107131

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...'
)

Upvotes: 1

Related Questions