1

I'm going through some refactoring to look for a flutter architecture/coding style that suits my sensibilities. I like many small independent blocks of code. So, I'm trying to subclass the AppBar widget for example. The problem I am having is that in my subclasses I cannot get access to the BuildContext for the ultimate top level widget. In the snippet below I cannot find the "Navigator" to switch pages since I do not have a context to pass to "of(context)".

So, the question: what is the idiomatic pattern I should use to subclass stateful widgets (eg AppBar) when my descendants classes will need access to the build context?

Thanks for your help.

import 'package:flutter/material.dart';

class MyBaseAppBar  extends AppBar {
  MyBaseAppBar( { actions, title }) : super( actions: actions, title: title);
}

class MyPageAppBar  extends MyBaseAppBar {
  static var myPageActions = <Widget>[
      IconButton( 
        icon: Icon(Icons.view_agenda), 
        onPressed: () =>Navigator.of( context ). pushNamed("agenda"))
  ];


  MyPageAppBar() : super( 
    title : Text("My App Bar"),
    actions : myPageActions
  );
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: MyPageAppBar(),
      body: Container() // for example
    );
  }
}

2 Answers 2

0

In your case why not pass the context in the AppBar constructor ? You could also create a method in your Stateless class(the class that calls the AppBar and pass it to the the constructor of your extended AppBar. Functions in dart are first class objects so you can store them in variables. Remember to avoid the closing parenthesis when passing as a parameter.

 class MyBaseAppBar  extends AppBar {  
    MyBaseAppBar( { actions, title, @required navigateTo}) : super( actions: actions, title: title);
  }

class MyPageAppBar  extends MyBaseAppBar {
   final var NavigateTo; //you could use the Navigator Object instead for the Datatype

   static var myPageActions = <Widget>[
     IconButton( 
    icon: Icon(Icons.view_agenda), 
    onPressed: () =>Navigator.of( context ). pushNamed("agenda"))
   ];


  MyPageAppBar({@required this.navigateTo}) : super( 
   title : Text("My App Bar"),
   actions : myPageActions
    );
 }


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

NavigateToFunc( Build context context)
{ 
   // Code to route
 }

  @override
  Widget build(BuildContext context) {
     return Scaffold
     /// You should be able to access the context in the 
      MyPageAppBar as it has its own build method
     appBar: MyPageAppBar(navigateTo: NavigateToFunc),
     body: Container() // for example
);

} } In regards to pattern, quite a few suggested techniques to address your challenge.

Have a look at this https://flutter.dev/docs/development/data-and-backend/state-mgmt/options

I have an inclination to the Provider plugin. You would wrap the parent widget in a ChangeNotifierProvider and the widgets(children) that would change in a Consumer or use the Provider.of.context to pass values between widgets. Additionally, you may not require to use Stateful widgets with provider. Wrap the widgets that change state with the Consumer

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I'm pretty familiar with the state options. This sort of thing is possible (medium.com/flutter-community/…). However, provider, etc seems overkill/not elegant in this case. The "AppBar" base class BuildContext() is called with the context. I feel there has to be an idiomatic inheritance mechanism to get at this.
0

I wound up doing this. https://medium.com/flutter-community/navigate-without-context-in-flutter-with-a-navigation-service-e6d76e880c1c

I still feel it is very lame to have to add provider and a service just to change pages but alas this seems to be the only way.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.