Integrate a Flutter app in to another flutter app - flutter

I have a bigger app named X and I have another smaller one named Y.
they are right now separate from each other and they are working fine.
I want to integrate app Y in X. I want to put codes of Y in X project but they should have a different Main so I can set different themes and routes.
Is there anyway to do that?
////update////
I upvoted all answers because they are all correct.
but if you know this one please answer.
I am using GetMaterialApp from GetX instead of MaterialApp.
and it returns error
'package:flutter/src/widgets/framework.dart': Failed assertion: line 5334 pos 14: '_dependents.isEmpty': is not true.
how can I fix this?

You can use multiple MaterialApp() in your project, combine the code/file like that the app is on another screen, and you will result in apps that have different references to their InheritedWidgets like Theme, Navigator, MediaQuery...
/*...*/
MaterialApp(
/*...*/
home: AppXHome(),
),
/*...*/
class AppXHome extends StatelessWidegt {
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Container(),
Container(),
MaterialApp(
home: AppYHome(),
),
],
),}}

You can use two MaterialApp widgets for defining separate routing ,
One for your APP X and other for Your APP Y,
Main function will remain the same no changes needed,
just create a route in APP X for app Y and wrap your App Y code in another MaterialApp Widget where you can define routes for APP Y.

Even if you integrate one or more apps into another app, there must be only one main after the whole merge.
So you need to move the other's main logic to the current one and then deal with the theme.
You can utilize this sample, which has three different apps in it with custom themes

Related

Overriding builder method of BeamLocation

I am currently trying to build a flutter app using Beamer and Provider. The app should have a BottomNavbar and remember the state of each tab when switching. Currently I am doing that by using nested Beamers with an IndexedStack.
Now I want to have a BeamLocation with multiple pages, that all share a common state. To do that I want to wrap the entire BeamLocation with a ChangeNotifierProvider. However when doing that, the app tries to build a Location of the wrapped BeamLocation after it already is on another BeamLocation. I am pretty sure the issue is with the builder method of BeamLocation:
When overriding it like this:
#override
Widget builder(BuildContext context, Widget navigator) => navigator
It works fine, which is expected since it doesn't really do anything.
But if I change it to this:
#override
Widget builder(BuildContext context, Widget navigator) {
return Container(
child: navigator,
);
}
It tries to build a page of that location, even when a different location from another BeamLocation is already active.
For a container this isn't a problem, but since I am trying to wrap the BeamLocation with a Provider as stated in the documentation, it is. When doing that, the extra build happens after the Provider is already gone, causing an error.

Flutter show SnackBar without context

I have a flutter app that makes many different http requests in different screens of the app. Now, I want to implement some general error handling, for example, whenever there is no connectivity, I want to show a SnackBar, no matter where I currently am in the app. I managed to write a method that gets called everytime there is an exception in one of my requests. Now, I want to show the SnackBar from within this method. But I don't have access to the BuildContext in this method, and I can't pass it as a parameter to the method either.
So, is there a way to show a SnackBar without having the context? For example, a method to get the context of the currently active screen, and then using it to show the SnackBar?
Suggesting to use a package as pointed by Kaival is not the right way to go, since you won't learn the right solution for your problem other than relying on 3rd party packages and also over-engineering your app with those when sometimes not needed.
Tu use a SnackBar without a context it's actually very simple through a key. You can create a GlobalKey<ScaffoldState> wherever you want and assign it to the Scaffold where you want to display the SnackBar.
GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
Widget build(BuildContext context) {
return Scaffold(key: _scaffoldKey);
}
and then anywhere you want, you can check its state to launch a SnackBar as such:
void foo() {
if(_scaffoldKey.currentState != null) {
_scaffoldKey.currentState.showSnackBar();
}
}
You just need to make sure the state is mounted (this is, the Scaffold you want is available, before displaying it.
Just make sure that you are using the new ScaffoldMessenger API you may want to consider adding it to your root MaterialApp a ScaffoldMessengerState so you can use it everywhere.
final GlobalKey<ScaffoldMessengerState> rootScaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
MaterialApp(
scaffoldMessengerKey: rootScaffoldMessengerKey,
home: ...
)
and call it accordingly
rootScaffoldMessengerKey.currentState.showSnackBar();
Refer to the docs for more info.
Hi you could use a globalkey as a navigation key associated with your MaterialApp. That would allow you to also navigate eventually to an error scree or anywhere else.
With the globalkey, you will be able to retrieve the context everywhere (at least when your app is in foreground and there actually is a context).
Although it is not always really reccomended to have a global variable, you can do Something like this:
In your main create a GlobalVariable class containing the key:
class GlobalVariable {
/// This global key is used in material app for navigation through firebase notifications.
static final GlobalKey<NavigatorState> navigatorState = GlobalKey<NavigatorState>();
}
Than declare the key as navigation key in your MaterialApp:
MaterialApp(
navigatorKey: GlobalVariable.navigatorState,
Finally access the key and context everywhere:
GlobalVariable.navigatorState.currentContext

How to scope providers on several widgets without putting the provider on a root widget in flutter

I'm working on a simple demo where the user logs in, sees a list of items, clicks on an item, and then sees its details. These are 3 screens but let's say two flows where one deals with login and the other with items.
I'm managing my state using provider package. I placed a LoginRepository provider on my root widget because that state is needed everywhere. This works great.
Now I need an ItemRepository which should be available on the ItemListScreen and the ItemDetailScreen. To implement that scoping, I decided to create a common ancestor widget called ItemScreens. This is where I placed my provider and my nested Navigator.
I navigate my screens using Navigator.of(context) to make sure the closes ancestor navigator is used. I fetch my provider using Provider.of<ItemRepository>(context) to make sure the closes ancestor state is used.
This apparently does not work because I get a Could not find the correct provider. I understand that the provider from the sibling route cannot be accessed by another sibling but here I'm nesting navigators I would expect the ItemRepository to be placed at ItemScreens which then handles subrouting so that these two routes can fetch providers from the parent route?
Sidenote:
Flutter documentation clearly states that providers should be lifted to achieve proper scoping. But I've never seen an example where the provider was lifted to a non-root widget. If all we can do is place providers into the root widget, that should be clearly stated.
EDIT: Re-creating providers on several widgets is kind of an alternative but that's not really scoping it's just pseudo passing by value.
EDIT: Putting all providers on the root widget with MultiProvider isn't a good idea because it creates a global state anti-pattern. Some states should also simply not be created unless needed i.e. the user is visiting that flow/screen.
You can wrap your MaterialApp Widget in main.dart with Multiprovider and give the list of providers you are using, That way App knows which class to treat as providers.
MultiProvider(
providers: [
ChangeNotifierProvider(
create: (_) => FirstProvider(),
),
ChangeNotifierProvider(
create: (_) => SecondProvider(),
),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Auro',
home: _decideMainPage(context),
// routes: routes,
theme: AllCoustomTheme.getThemeData(),
),
)

Notification to adjacent widget

I have a widget that contains a "save" button. After pressing that button several other widgets (not only ancestor ones) must save its state to the file. I don't know how to inform them. What is the best way to achieve that in flutter? I was thinking about using Notification in the "save" widget, closest shared ancestor would contain a NotificationListener that triggers an event to which every widget will subscribe. For me, it doesn't look like a solution.
Provider is the recommended way to do State Management for apps of all sizes. -–Chris Sells – Product Manager, Flutter. June 19, 2019
It's pretty complicated at first, best to check out Simple app state management
The ChangeNotifier uses the notifyListeners function whenever there is any change in the class:
class ChangeNotifierModel extends ChangeNotifier {
String stringThatChanges = 'startValue';
void changeTheString(String value) {
stringThatChanges = value;
notifyListeners();
}
}
The only code that is specific to ChangeNotifier is the call to notifyListeners(). Call this method any time the model changes in a way that might change your app’s UI.
I'm pretty new to Flutter myself, but the way I understand it so, it kinda acts like a wrapper, e.g. wrapping the child of main.dart
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => SingleNotifier())
],
child: MyApp(),
));
don't forget the dependencies
dependencies:
provider: ^4.3.2+2

Flutter - How to handle Navigation without using MaterialApp?

In flutter creating named routes is easy and logical, but only when returning a MaterialApp.
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
initialRoute: "/";
return MaterialApp( //gives errors when I return a Container
routes: {
"/" : (context) => FirstRoute(),
"/second route" : (context) => SecondRoute()
}
);
}
}
I am not that big a fan of Material Design and want to create a UI from my own design.
But when I apply the same pattern when returning a container I get an error.
So my qustion is how do I have named route setup with a vanilla Flutter App or am I being forced to use MaterialApp for my project?
Thanks in advance
MaterialApp is just a collection of commonly used components such as a navigator. You could also use a CupertinoApp. Material uses iOS navigation animations on iOS and Android animations on android. Though you’re not stuck to the UI design because you’re using a MaterialApp as a foundation. You are able to build whatever UI you want with a material app or even use Cupertino widgets. It’s all up to you.