3

The class StatelessWidget is marked as immutable. However, I am using the scoped model, which means that I avoid StatefulWidget and use the model to alter state in StatelessWidget. This leads to me having non-final fields in StatelessWidget, which doesn't cause errors, because it's just a warning. But I wondered if there is a better way?

footurist
  • 1,509
  • 2
  • 16
  • 23

2 Answers2

9

Stateless widgets should only have final fields, with no exceptions. Reason: When the parent widget is rebuilt for some reason (screen rotation, animations, scrolling...), the build method of the parent is called, which causes all widgets to be reconstructed.

Classes the extend StatefulWidget must follow the same rule, because those are also reconstructed. Only the State, which can contain mutable fields, is kept during the lifetime of widget in the layout tree.

There is no reason to avoid StatefulWidget. It is a fundamental building block of Flutter.

In fact, ScopedModelDescendant is also a stateful widget. The primary benefit of scoped_model is that you can separate the business logic from the widget layer. It doesn't eliminate the need for stateful widgets.

Use stateful widgets for:

  • Injecting scoped models into the tree (the widget that builds the ScopedModel widget). Store the Model instance in the State.
  • Storing user input (TextEditingController, state of a checkbox)
  • Animated widgets which require AnimationControllers
  • To store anything that ends with Controller (TabController, ScrollController, ...)

It is often a good idea to make the "page" widgets (widgets which build a Scaffold, accessible using the Navigator) stateful. Often these are the hosts for scoped models.

boformer
  • 28,207
  • 10
  • 81
  • 66
  • Very helpful! Do you think it would be a mistake to have a ScopedModel wrapped around the root MaterialApp, which acts as a "manager" and has instances of all other models in it to make them accessible from all parts of the app? Would this impact performance negatively? – footurist Nov 07 '18 at 16:33
  • 1
    It won't affect performance, but it would be cleaner to use a separate `ScopedModel` widget for each model you need (just interlace them, again no performance impact). – boformer Nov 07 '18 at 17:23
  • 1
    Only create a scoped model if you need the `notifyListeners` feature. In general, if you only need to provide some kind of "global" service, you can use a simple `InheritetWidget` that provides the service (the service would be a simple class) – boformer Nov 07 '18 at 17:26
  • 1
    I really recommend you to look at the source code of scoped_model to understand what's going on – boformer Nov 07 '18 at 17:27
  • I just did that. And I wondered if scoped model is the right approach for me anyways. If you don't mind I would describe the problem I have with architecture really quick: I like to have very short classes, because it helps me to keep oversight. In practise I would create a widget for each page, then for each ui part of the page and then maybe split each of those again if they have a lot of content. – footurist Nov 07 '18 at 17:35
  • The problem: I need communication between them. And to avoid some sort of constructor hell, I tried this scoped model "manager" approach which nests scoped models for each class that I create so that I have access to them from all parts of the app (lazy I know). – footurist Nov 07 '18 at 17:36
  • Do you think there is a better approach to accomplish what I want while keeping the "short class structure" that helps me keep oversight and being able to trigger rebuilds of those classes from anywhere? – footurist Nov 07 '18 at 17:37
0

Here's you question:

Do you think there is a better approach to accomplish what I want while keeping the "short class structure" that helps me keep oversight and being able to trigger rebuilds of those classes from anywhere?

What you're asking for here ↑ seems to be one more app state management approach that should be better than scoped model.

As you know, app state management approaches are a set of techniques that allow you as a developer:

  • to bind data with widgets.

Binding data with widgets, in turn, helps you as a developer:

  • to rebuild widgets automatically on every change of bound data.

Maybe, for that purpose, you can make use of rxdart:

Here you will find some very helpful list of app state management approaches that can lead you to a better way of app development: