I have code as below, it's no problems.
void main() async {
Widget _defaultHome = new LoginPage();
runApp(new MaterialApp(
title: 'App',
debugShowCheckedModeBanner: false,
home: _defaultHome,
routes: <String, WidgetBuilder>{
// Set routes for using the Navigator.
'/tabs': (BuildContext context) => new TabsPage(),
'/login': (BuildContext context) => new LoginPage()
},
));
}
I want to change it to code as below, how can I pass _defaultHome to class MyApp?
void main() async {
Widget _defaultHome = new LoginPage();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
// final textTheme = Theme.of(context).textTheme;
return MaterialApp(
title: 'Gaia',
debugShowCheckedModeBanner: false,
home: _defaultHome,
routes: <String, WidgetBuilder>{
// Set routes for using the Navigator.
'/tabs': (BuildContext context) => new TabsPage(),
'/login': (BuildContext context) => new LoginPage()
},
);
}
}
Use the below code and any parameter can pass through constructor.
void main() async {
Widget _defaultHome = new LoginPage();
runApp(MyApp(defaultHome: _defaultHome,));
}
class MyApp extends StatelessWidget {
final Widget defaultHome;
const MyApp({
#required this.defaultHome,
Key key,
}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
// final textTheme = Theme.of(context).textTheme;
return MaterialApp(
title: 'Gaia',
debugShowCheckedModeBanner: false,
home: defaultHome,
routes: <String, WidgetBuilder>{
// Set routes for using the Navigator.
'/tabs': (BuildContext context) => new TabsPage(),
'/login': (BuildContext context) => new LoginPage()
},
);
}
}
You can either decide to pass it via Provider or via parameters.
This is the way you pass it via parameters with optional parameters:
void main() async {
final Widget _defaultHome = new LoginPage();
runApp(MyApp(homePage: _defaultHome));
}
class MyApp extends StatelessWidget {
MyApp({this.homePage});
final Widget homePage;
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
// final textTheme = Theme.of(context).textTheme;
return MaterialApp(
title: 'Gaia',
debugShowCheckedModeBanner: false,
home: _defaultHome,
routes: <String, WidgetBuilder>{
// Set routes for using the Navigator.
'/tabs': (BuildContext context) => new TabsPage(),
'/login': (BuildContext context) => homePage
},
);
}
}
You can pass it by a parameters in your constructor and assign it to your home.
class MyApp extends StatelessWidget {
// This widget is the root of your application.
final Widget defaultHome;
const MyApp({Key key, #required this.defaultHome}) : super(key: key);
#override
Widget build(BuildContext context) {
// final textTheme = Theme.of(context).textTheme;
return MaterialApp(
title: 'Gaia',
debugShowCheckedModeBanner: false,
home: defaultHome,
routes: <String, WidgetBuilder>{
// Set routes for using the Navigator.
'/tabs': (BuildContext context) => new TabsPage(),
'/login': (BuildContext context) => new LoginPage()
},
);
}
}
Related
1. this is code flutter flavor
2. I cannot using context for read ex: context.read(flavorConfiProvider)
var flavorConfigProvider;
void mainCommand(FlavorConfig config) {
flavorConfigProvider = StateProvider((ref) => config);
runApp(
ProviderScope(
child: MyApp()
),
);
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final config = context.read(flavorConfigProvider);
return MaterialApp(
title:config.state.appTitle,
theme:config.state.theme,
home: const MyHomePage(),
);
}
}
im trying to use StreamProvider with MultiProvider in MaterialApp
when I try accessing the provider, I get the following error:
Error: Could not find the correct Provider above this MyApp Widget
main.dart
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
final provider = Provider.of<SignInProvider>(context, listen: false);
return MultiProvider(
providers: [
StreamProvider<UserModel>.value(value: provider.authStateChange())
],
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primaryColor: primaryColor,
accentColor: secondaryColor,
textTheme: customTextTheme
),
home: AuthHandler()
),
);
}
}
class AuthHandler extends StatelessWidget {
#override
Widget build(BuildContext context) {
UserModel _userModel = Provider.of<UserModel>(context);
return (_userModel != null) ? HomeScreen() : LoginScreen();
}
}
user_model.dart
class UserModel {
String uid;
String displayName;
String photoURL;
String email;
UserModel({ this.uid, this.displayName, this.photoURL, this.email, });
}
signin_provider.dart
Stream<UserModel> authStateChange() {
return firebaseAuth.authStateChanges().map((User user) => (user != null) ? UserModel(uid: user.uid) : null);
}
Go to main.dart and Add Your Provider :
Example :
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<ThemeBloc>(
create: (_) => ThemeBloc(),
child: Consumer<ThemeBloc>(
builder: (_, mode, child) {
return MultiProvider(
providers: [
ChangeNotifierProvider<SignInBloc>(
create: (context) => SignInBloc(),
),
ChangeNotifierProvider<NewsDataBloc>(
create: (context) => NewsDataBloc(),
),
ChangeNotifierProvider<PopularDataBloc>(
create: (context) => PopularDataBloc(),
),
],
child: MaterialApp(
home: MyHomePage()),
);
},
),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return WelcomePage();
}
}
I apply the same bloc pattern in the login and signup form,when i have only one provider, is not a problem. But now i implement second provider. This provider controller a page view, the index and other parameters. The problem is that i implement multiprovider, when i start login page i have an error.This is my code.
class MyApp extends StatelessWidget {
//final _prefs = new PreferenciasUsuario();
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => new UiProvider()),
Provider(create: (_) => new BlocFormProvider())
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demos',
initialRoute: 'init',
routes: {
'init': (BuildContext context) => InitialPage(),
'login': (BuildContext context) => LoginPage(),
'signup': (BuildContext context) => SignUpPage(),
'home': (BuildContext context) => HomePage(),
'remember': (BuildContext context) => RememberPasswordPage(),
'start': (BuildContext context) => StartPage()
}),
);
}
}
and this is my bloc provider
import 'package:flutter/material.dart';
import 'login_bloc.dart';
class BlocFormProvider extends InheritedWidget {
static BlocFormProvider _instancia;
factory BlocFormProvider({Key key, Widget child}) {
if (_instancia == null) {
_instancia = new BlocFormProvider._internal(key: key, child: child);
}
return _instancia;
}
final loginBloc = LoginBloc();
BlocFormProvider._internal({Key key, Widget child})
: super(key: key, child: child);
#override
bool updateShouldNotify(covariant InheritedWidget oldWidget) => true;
static LoginBloc of(BuildContext context) {
return context
.dependOnInheritedWidgetOfExactType<BlocFormProvider>()
.loginBloc;
}
}
Finally this is the error:
The getter 'loginBloc' was called on null.
Receiver: null
Tried calling: loginBloc
The relevant error-causing widget was LoginPage
Thanks for your help.
I'm new to flutter, In MaterailApp Widget have an attribute called onUnknownRoute. What is the main use of onUnknownRoute?
Thanks for your help!
You can copy paste run full code below
In flutter web, when user manually key a undefine route, it can produce like 404 effect
full code
import 'package:flutter/material.dart';
void main() {
runApp( MaterialApp(
initialRoute: "/screen1",
routes: <String, WidgetBuilder>{
'/screen1': (BuildContext context) => Screen1(),
'/screen2': (BuildContext context) => Screen2(),
'/screen3': (BuildContext context) => Screen3(),
'/screen4': (BuildContext context) => Screen4()
},
onUnknownRoute: (RouteSettings settings) {
return MaterialPageRoute<void>(
settings: settings,
builder: (BuildContext context) =>
Scaffold(body: Center(child: Text('Not Found'))),
);
},
)
);
}
class Screen1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container();
}
}
class Screen2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container();
}
}
class Screen3 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container();
}
}
class Screen4 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container();
}
}
onUnknownRoute property is used to handle the worst case when the app navigation fails to get a route. If not handled, exception will be generated.
The navigator widget manages a stack of Route objects.
Route objects are nothing but full-screen elements like "screens" or "pages".
The navigator manages navigation between the screens in any app.
The Navigator for any app is only built if routes are provided by one of below items
home
routes
onGenerateRoute
onUnknownRoute
If the app only has one page, then you can specify it using home.
Else all routes will be in routes table including the home
If a route is requested that is not specified in routes table (or by home), then the onGenerateRoute callback is called
when even onGenerateRoute fails to generate a route, the property OnUnknownRoute will be triggered to handle the scenario.
We can handle an unknown route as below,
return MaterialApp(
title: 'Named Routing',
onGenerateRoute: router.generateRoute,
onUnknownRoute: (settings) => MaterialPageRoute(
builder: (context) => UndefinedView(
name: settings.name,
)),
initialRoute: HomeViewRoute,
);
If unknown route event is not handled using the onUnknownRoute property, flutter may throw an exception
The solution is coding in routes -> Example
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Material App',
// home: HomePage(),
initialRoute: '/',
routes: <String, WidgetBuilder>{
'/': (BuildContext context) => HomePage(),
'alert': (BuildContext context) => AlertPage(),
'avatar': (BuildContext context) => AvatarPage(),
},
***onUnknownRoute: (settings) {},***
onGenerateRoute: (settings) {
return MaterialPageRoute(
builder: (BuildContext context) => AlertPage());
},
);
}
}
I have got follow app:
class MyAppState extends State<MyApp>
{
TenderApiProvider _tenderApiProvider = TenderApiProvider();
Future init() async {
await _tenderApiProvider.getToken();
}
MyAppState()
{
init();
}
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(builder: (_) => _tenderApiProvider),
],
child: MaterialApp(
title: "My App",
routes: {
'/': (context) => HomePage(),
'/splash-screen': (context) => SplashScreen(),
'/result_table': (context) => ResultDataTable(),
}
),
);
}
}
I need to draw firstly SplashScreen current code show at start HomePage.
In splash-screen I need to switch to HomePage after all data loaded. Here it's code:
Widget build(BuildContext context) {
TenderApiProvider apiProv = Provider.of<TenderApiProvider>(context);
return StreamBuilder(
stream: apiProv.resultController,
builder: (BuildContext context, AsyncSnapshot snapshot) {
//...
if(apiProv.apiKeyLoadingState == ApiKeyLoadingState.Done && apiProv.regionsLoadingState == RegionsLoadingState.Done)
{
Navigator.of(context).pushNamed("/"); // Should it be placed in Build??
}
});
}
Could you help me and show to to draw at app start SplashScreen and then switch from it to HomePage?
You will need to wrap your SplashScreen() inside a StatefulWidget so you can fetch your data in initState(). It is important to wrap fetch() logic inside a SchedulerBinding.instance.addPostFrameCallback() to access the BuildContext inside initState(). Also, that way, you avoid conflicts with RenderObjects that get destoryed while they are actually build.
Following a complete minimal example.
EDIT: You cant use await in initState({}).
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Wrapper(),
);
}
}
class Wrapper extends StatefulWidget {
#override
_WrapperState createState() => _WrapperState();
}
class _WrapperState extends State<Wrapper> {
#override
void initState() {
super.initState();
SchedulerBinding.instance.addPostFrameCallback((_) {
_loadDataAndNavigate()
});
}
_loadDataAndNavigate() async {
// fetch data | await this.service.fetch(x,y)
Navigator.of(context).pushNamed('/');
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SplashScreen(),
);
}
}
i use splashScreen
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: SplashHome(),
routes: <String, WidgetBuilder>{
'/HomeScreen': (BuildContext context) => new ImageHome()
},
);
}
}
class SplashHome extends StatefulWidget{
#override
State<StatefulWidget> createState() {
return _SplashHome();
}
}
const timeout = const Duration(seconds: 2);
class _SplashHome extends State<SplashHome>{
startTimeout() {
return new Timer(timeout, handleTimeout);
}
void handleTimeout() {
Navigator.of(context).pushReplacementNamed('/HomeScreen');
}
#override
void initState() {
super.initState();
startTimeout();
}
#override
Widget build(BuildContext context) {
return new Container(
color: Colors.lightBlue,
);
}
}