How can I use SharedPreferences to save a list of Strings in Flutter - flutter

I am trying to save a list of strings in flutter by using SharedPreferences. But my problem is that I have 8 different class in one .dart page and I want to display the saved strings on all the classes, so the SharedPreferences fonction has to be written outside of any class.
Here's one part of my 3000 line of code.
*`So my SharedPreferences fonction has to be outside of any classes (in this case here) and I need to be able to read it from the inside of the _MainScreenState class (in the text)`*
class MainScreen extends StatefulWidget {
#override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
#override
Widget build(BuildContext context) {
return Container(
child: Text('one of the saved string value has to appear here');
);
}
}

Inserting a List into shared preferences is pretty straight forward. Have a look here: Can i put List into SharedPreferences in Flutter?
As for accessing it. SharedPreferences are available from anywhere in your App. So getting them to your classes should not be an issue. I would try with a static function, something like this:
class TestClass{
//This is available from anywhere in your project
//TestClass.getList();
static List<String> getList(){
//Get your list from preferences
//and return it.
}
}

Related

How to send data from one widget to multiple widgets while Navigating in flutter?

Actually I was working on a GoogleSignIn button, where when signed in, I am navigating and sending data to another widget/page for the Drawer. What I want is that this accessed data from google should be sent to all other drawers built in scaffold for my entire app. I know there is a better approach for Global drawer, but having different drawers for each of my scaffold is my app's requirement.
This is the first widget's code:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
RestaurantHome(detailsUser: details)));
This is code of where I'm getting data using constructor for other widget.
class Home extends StatefulWidget {
final UserDetails detailsUser;
Home({Key key, this.detailsUser}) : super(key: key);
#override
_HomeState createState() => _HomeState();
}
In above scenario, I'm only able to send data to Home class using constructor. But I actually want to send data to multiple classes for accessing drawer details there while navigating at once.
Please guide me the best approach in this problem.
Think of me as a beginner. Thanks
you could provide your user details class by the entire app, a recommend using get_it(https://pub.dev/packages/get_it) to that
you create a class like:
class AuthController {
UserDetails detailsUser;
}
on login function:
void login() {
/// do whatherver you want
getIt<AuthController>().detailsUser = details;
}
on anywhere in your app
class Home extends StatefulWidget {
final UserDetails detailsUser = getIt<AuthController>().detailsUser;
Home();
#override
_HomeState createState() => _HomeState();
}
so this way you can acess the user details in any of your drawers.
just take a look at get_it documentation to see how to configure it, it's simple.
You can do this thing with redux ,provider,bloc. there is multiple to get data in any where in app.
If you want to create this pattern I can help your.

Transfer variable to other class

I am trying to get a list from class to the other. But I want it to only be transferred after it has got a value assigned from a Future. Is there a way to do so (something like a setState method that acts across classes) My code is here:
class Design extends StatefulWidget {
#override
_DesignState createState() => _DesignState();
}
class _DesignState extends State<Design>{
var Data;
#override
void initState() {
super.initState();
comparer().then((List returnedV){
setState(() {
Data = returnedV;
});
});
}
Future<List> compare() async {
...
return dataDevice
}
}
class AboutSheet extends StatefulWidget {
final List Data;
AboutSheet({#required this.Data});
#override
_AboutSheetState createState() => _AboutSheetState();
}
class _AboutSheetState extends State<AboutSheet> {
}
Every time I use the variable Data in the second class it has the value null. I think it's because I have defined it before with the value null and it's pulling that and is not waiting for the future to assign a value to it. I can't think of a workaround. I would really appreciate your help!
What you are referring to is a state management solution. There is a lot of them, with each their pros and cons. I (and the Flutter team) would suggest Provider.
Take a look at this : List of state management approaches

How do I preserve the data in my textfield when navigating to another tabview

How do I preserve my data when I navigate between two different tabs in Flutter... Basically what I want to achieve is, on one side of the tab, I see users data, and on the other side of the tab, I want to be able to copy some of those user data and paste into some textfields on the other tab without losing the data in the text fields when I navigate back and forth and still also preserving the level of scrolling I might have done on the tab where the users data show.
You need to use AutomaticKeepAliveClientMixin This will ensure the State instance is not destroyed when leaving the screen.Extend your every tabview's state class with it and create an override method wannaKeepAlive and set it to true.Here is an example of a widget using AutomaticKeepAliveClientMixin.
class Example extends StatefulWidget {
#override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> with AutomaticKeepAliveClientMixin {
#override
Widget build(BuildContext context) {
return Container(
);
}
#override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
}

Flutter: How can I avoid recreating the model for parts of the application?

My app uses a set of Card()s inside a PageView(), each card has multiple text lines.
The user gives input for each line (e.g. modifying the text etc.).
I want to keep this input for a while.
This is how my code looks at the moment, abstractly speaking:
class MyCard extends StatefulWidget {
final List<Widget> _myLines = [];
#override
State<StatefulWidget> createState() => MyCardState();
}
class MyCardState extends State<MyCard> {
...
#override
Widget build(BuildContext context) {
...
widget._myLines.add(ChangeNotifierProvider(
create: (context) => MyLineModel(context, lineText),
child: RecipeLine())
...
}
}
This doesn't work well:
As soon as I swipe left / right through the PageView onto other cards and then swipe back, the Card is being built again. This also leads to a rebuild of MyLineModel, which in turn erases all the user's input.
How can I avoid the rebuild of MyLineModel and keep the user's input?
You can solve this in 2 ways:
Create the model outside the widget and pass the model for the widget, as a variable to a constructor for example, or using Provider or any other technique of Dependency Injection.
Using any of the KeepAlive APIs, such as the AutomaticKeepAliveClientMixin as:
class MyCardState extends State<MyCard> with AutomaticKeepAliveClientMixin {
...
#override
bool get wantKeepAlive => true;
}
As the official documentation states, we can simply use the ChangeNotifierProvider.value() constructor...
In the original code:
class MyCardState extends State<MyCard> {
...
#override
Widget build(BuildContext context) {
...
widget._myLines.add(ChangeNotifierProvider.value(
value: MyLineModel(context, lineText),
child: RecipeLine())
...
}
}

Why build method isn't defined inside StatefulWidget?

I'm currently learning Flutter. I tried to deep dive into Flutter Widget life-cycle, and I wonder why StatefulWidget are written like this :
class Example extends StatefulWidget {
#override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
// initState
// setState
// ...
#override
Widget build(BuildContext build) {
...
}
}
but not :
class Example extends StatefulWidget {
// initState
// setState
// ...
#override
Widget build(BuildContext build) {
...
}
}
I think the latter makes the source simple. But I don't know why they're using the former style ?
The reason why StatefulWidget uses a separate State class and not having build method inside its body is because all fields inside a Widget are immutable, and this includes all its sub-classes.
You might have noticed that StatelessWidget has its build and other associated methods defined inside it, but that was possible due to the nature of StatelessWidget which is rendered completely using the provided info, and doesn't expect any future change in its State.
In the case of StatefulWidget, State information occasionally change (or expected to change) during the course of the app, thus this information isn't suitable for storage in a final field (build) to satisfy Widget class conditions (all fields are immutable). That's why State class is introduced. You just have to override the createState function to attach your defined State to your StatefulWidget, and let all that change happens in a separate class.