Search code examples
flutterproviderstate-management

Best Practice for Data Transfer Between Pages in Flutter: Provider vs Direct Passing


I'm exploring the best practices for transferring data between pages in Flutter and find myself caught between two approaches: utilizing a Provider for centralized data management versus directly passing values to the next page. I'd like to gather insights into the advantages and disadvantages of each method, especially in terms of app architecture, maintainability, and performance implications.

  1. Provider Approach: How does using a Provider for state management and data transfer affect app performance and scalability? Are there specific cases or app sizes where this method shines or falls short?
  2. Direct Passing: Conversely, when might directly passing values between pages be more advantageous? Are there performance benefits or limitations to consider, especially with larger datasets or more complex objects?
  3. Scenarios and Performance: Are there particular scenarios where one method is clearly preferable over the other? Additionally, how do these methods impact the app's overall performance, especially as the app grows?

I'm seeking advice from the Flutter community on which approach might be more suitable for different use cases and any best practices or patterns that have been effective in your experience. Thank you!


Solution

  • data management is very important. you have to understand the data flow between screen and modules.

    my preference is like this:

    • if i have 3 modules that access user profile data. so i have to put user profile data to state management. since 3 modules could possibly change the user profile data
    • then when i have search screen which contain date time filter (from date and to date), then i have to show the result on new screen then also showing the date filter on result screen like "filtering date x to date y". the data update happened one sided (the result screen don't have the right to update the data). in this case, you need to pass the arguments

    bonus: when passing arguments, i make class to make things easier

    class InvoiceResultViewArgs {
      const InvoiceResultViewArgs({
        required this.viewEnum,
        required this.from,
        required this.to,
      });
    
      final InvoiceViewEnum? viewEnum;
      final DateTime? from;
      final DateTime? to;
    }
    
    class InvoiceResultView extends StatefulHookConsumerWidget {
      const InvoiceResultView({
        required this.args,
        super.key,
      });
    
      static const String routeName = '/invoice_result_view';
      final InvoiceResultViewArgs args;
    
      @override
      ConsumerState<ConsumerStatefulWidget> createState() =>
          _InvoiceResultViewState();
    }
    

    somewhere on routes file:

      if (settings.name == InvoiceResultView.routeName) {
        if (settings.arguments is InvoiceResultViewArgs) {
          InvoiceResultViewArgs args =
              settings.arguments as InvoiceResultViewArgs;
    
          return InvoiceResultView(args: args);
        }
    
        return const MissingArgumentView();
      }
    

    this will makes things a lot easier and clean also i use riverpod, makes it even cleaner

    just makesure that you separate business logic and data..