How do I define an Abstract Widget?

857

I think what you really want is something like this and I will use Flutter Dart code instead of pseudocode:

class Vehicle extends StatelessWidget {
  final int type;
  final String name;
  final Widget list, edit, settings;

  const Vehicle({Key key, this.type, this.name, this.list, this.edit, this.settings}) : super(key: key);

  @override
  Widget build(BuildContext context) => Row(children: <Widget>[list, edit, settings]);
}

class Truck extends StatelessWidget {
  const Truck({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) => Vehicle(
        type: 1,
        name: 'Truck',
        list: Column(),
        edit: const Icon(Icons.edit),
        settings: Checkbox(),
      );
}

class Car extends StatelessWidget {
  const Car({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) => Vehicle(
    type: 2,
    name: 'Car',
    list: Column(),
    edit: const Icon(Icons.edit_location),
    settings: ToggleButtons(...),
  );
}

As you can see, you can have a predefined Vehicle class that defines parameters and also handles laying out all the information you want to dynamically display for different vehicles.
Now, you can implement a specific vehicle by creating another widget that returns Vehicle in its build method.

Obviously, the layout widgets I chose Row, Column, etc. are only meant as placeholders, but you can actually implement your layout logic using this approach.

I would say that this is a more idiomatic approach for widgets.


Regarding your example: you should probably not store widgets in a List when using ListView.builder, but you can dynamically instantiate your widgets in the builder function. This is also better performance-wise if you can utilize ListView.builder. If you cannot dynamically create your items, you can just use ListView instead and store your widgets in a list.

builder: () {
  if (items[index]['type'] == 'car')
    return Car(...);

  return Truck(...);
}
Share:
857
user3072517
Author by

user3072517

Updated on December 15, 2022

Comments

  • user3072517
    user3072517 over 1 year

    Since Dart/Flutter uses a composition style approach to building widgets (coupling that with how scoped model operates) what is a good pattern for developing a library of objects that encapsulate widgets?

    Assume you have an application that allows you to display a list of objects within a list view that each have their own way displaying their information, but all have the same approach for doing so.

    Consider the following pseudo-code, which takes the approach of encapsulating all of the required widgets and other such properties/methods needed for each object to follow.

    abstract class Vehicle {
      int type;
      String name;
      Widget listWidget
      Widget editWidget
      Widget settingsWidget
    }
    
    class Truck extends Vehicle {
      type = 1
      name = "Truck"
      listWidget = ... My truck widget for within lists...
      editWidget = ... My truck edit widget ...
      settingsWidget = ... My truck settings display ...
    }
    
    class Car extends Vehicle {
      type = 1
      name = "Car"
      listWidget = ... My car widget for within lists...
      editWidget = ... My car edit widget ...
      settingsWidget = ... My car settings display ...
    }
    

    With that approach, then I would have to create each vehicle type and follow the abstract api pattern and not worry about how it is rendered.

    When it comes to displaying the vehicles within a list (ListView for example), this approach would allows the object itself to dictate how it is rendered in that list, and it could be unique to each type of vehicle.

    For example:

        Container(
            child: new ListView.builder(
                itemCount: items.length,
                itemBuilder: (BuildContext ctxt, int index) {
                    return items[index].listWidget;
                }
            )
        )
    

    Is this a valid Dart/Flutter way of accomplishing this or is there a better pattern that should be followed?

    Am I violating Dart recommended coding patterns in that each widget would control it's own display?

    The idea behind this is that if a settings panel needed to be formatted differently depending on the type of vehicle, I could do it, rather than trying to figure out how to create a common display pattern for all widgets.

    Thoughts?

  • user3072517
    user3072517 over 4 years
    Ah yes! Reversing the encapsulation and returning a vehicle instead. That seems a much cleaner way of handling an extensible class rather than trying to build up an inheritance model approach.