item property

_Item<T, P> item
latefinal

Optimized for item displaying. Used with

Working with a list of items, we may want to display them using the ListView widget of Flutter. At this stage, we are faced with some problems regarding :

  • performance: Can we use the const constructor for the item widget. Then, how to update the item widget if the list of items updates.
  • Widget tree structure: What if the item widget is a big widget with its nested widget tree. Then, how to pass the state of the item through the widget three? Are we forced to pass it through a nest tree of constructors?
  • State mutation: How to efficiently update the list of items when an item is updated.

InjectedCRUD, solves those problems using the concept of inherited injected. Injected.inherited

Example:

inherited

products.inherited({
    required Key  key,
    required T Function()? item,
    required Widget Function(BuildContext) builder,
    String? debugPrintWhenNotifiedPreMessage,
 })

Key is required here because we are dealing with a list of widgets with a similar state.

Example:

Widget build(BuildContext context) {
  return OnReactive(
       ()=>  ListView.builder(
          itemCount: products.state.length,
          itemBuilder: (context, index) {
            //Put InheritedWidget here that holds the item state
            return todos.item.inherited(
              key: Key('${products.state[index].id}'),
              item: () => products.state[index],
              builder: (context) => const ProductItem(),//use of const
            );
          },
        );
  );

In the ListBuilder, we used the inherited method to display the ItemWidget. This has huge advantages:

  • As the inherited method inserts an InheritedWidget aboveItemWidget , we can take advantage of everything you know about InheritedWidget.
  • Using const constructors for item widgets.
  • Item widgets can be gigantic widgets with a long widget tree. We can easily get the state of an item and mutate it with the state of the original list of items even in the deepest widget.
  • The inherited method, binds the item to the list of items so that updating an item updates the state of the list of items and sends an update request to the database. Likewise, updating the list of items will update the ItemWidget even if it is built with the const constructor.

call(context)

From a child of the item widget, we can obtain an injected state of the item using the call method:

Inherited<T> product = products.item.call(context);
//item is callable object. `call` can be removed
Inherited<T> product = products.item(context);

You can use the injected product to listen to and mutate the state.

product.state = updatedProduct;

Here we mutated the state of one item, the UI will update to display the new state, and, importantly, the list of items will update and update query with the default parameter is sent to the backend service.

Another important behavior is that if the list of items is updated, the item states will update and the Item Widget is re-rendered, even if it is declared with const constructor. (This is possible because of the underlying InheritedWidget).

of(context)

It is used to obtain the state of an item. The BuildContext is subscribed to the inherited widget used on top of the item widget,

T product = products.item.of(context);

of(context) vs call(context):

  • of(context) gets the state of the item, whereas, call(context) gets the Injected object.
  • of(context) subscribes the BuildContext to the InheritedWidget, whereas call(context) does not.

reInherited

As we know InheritedWidget cannot cross route boundary unless it is defined above the MaterielApp widget (which s a nonpractical case).

After navigation, the BuildContext connection loses the connection with the InheritedWidgets defined in the old route. To overcome this shortcoming, with state_rebuilder, we can reinject the state to the next route:

RM.navigate.to(
  products.item.reInherited(
     // Pass the current context
     context : context,
     // The builder method, Notice we can use const here, which is a big
     // performance gain
     builder: (BuildContext context)=>  const NewItemDetailedWidget()
  )
)

Implementation

late final _Item<T, P> item = _Item<T, P>(this as InjectedCRUDImp<T, P>);