I am coming from React and trying to understand Flutter. There are some differences between dart vs JS and React vs Flutter. However, it seems a bit similar to each other. However, there is some confusion toward Flutter.
void
It does not return the value. Therefore, it is used to void main(). Does it mean like the function 'main()' will be executed and I will never be able to reuse void main()?
<>
In the code, I have here
class LoginScreen extends StatefulWidget {
createState() {
return new LoginScreenState();
}
}
class LoginScreenState extends State<LoginScreen> {
Widget build(context) {
return Container(
margin: EdgeInsets.all(20.0),
child: Column(
children: [
emailField(),
// passwordField(),
// submitButton(),
],
));
}
}
I can see that State<LoginScreen> is related to class LoginScreen. It is an extension of the LoginScreen State?
Future<int> successor = future.then((int value) {
},
However, in here Future <----- I do not understand why it has to state 'int' in this code. What is the proper use of <>?
Stateful vs Stateless
Can I just use the Stateful all the time even if I do not have any state like React? Where there is no difference?
You need to learn basic dart.
void main() is same as main(). The only difference is declaring the return type. main() is called only once by the flutter engine.
Read about generics. <> is the called the diamond operator and is used to specify the type of something. Future<int> means the function will return something in future and it will strictly be of int type. If you don't specify the type flutter will treat it as dynamic.
You can use stateful classes if you are using state management packages like provider or rxdart to maintain state.
class LoginScreen extends StatefulWidget {
createState() {
return new LoginScreenState();
}
}
enter code here
changed to
class LoginScreen extends StatefulWidget {
LoginScreenState createState()=>LoginScreenState();
}
}
enter code here
Stateful vs Stateless`enter code here`
stateful has state object and stateless has no state object.using stateful you can changes widget data .on other hand in stateful you cant
Related
I have created a widget in Flutter as follows:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class WidgetA<T> extends StatefulWidget {
const WidgetA({
super.key,
required this.errorSelector,
...
});
final Function errorSelector;
...
#override
State<WidgetA> createState() =>
_WidgetAState<T>();
}
class _WidgetAState<T> extends State<WidgetA> {
...
#override
Widget build(BuildContext context) {
...
return Builder(
builder: (ctx) {
final String foo =
ctx.select(widget.errorSelector as String Function(T));
return Text(foo);
}
);
}
}
Is this practice okay?
Are there better ways to accomplish this?
Can this cause any issues?
FYI - T is being used to pass a Class that extends a Bloc.
it's not bad and it's not good unless you have a good reason to do it (for example if you want to customize a data type based on that generic ).
so before doing it, ask yourself why so I need to make it generic, all the good patterns in the code are there to add some value to the code.
as you can see the only place where the generic is important is to set it in the State object, this prevents conflicting your StatefulWidget in your app with others and specify it to one StatefulWidget
I have seen many times people calling widget. sth inside the code.
May I know what it is actually doing?
For example code below, (highlighted part is my confusion)
class _MyOwnClassState extends State<MyOwnClass> {
#override
Widget build(BuildContext context) {
return ListTile(
title: Container(
child: Column(children: makeWidgetChildren(**widget.jsonObject)**),
),
);
}
}
In flutter's StatefulWidget, we have the following architecture.
You have a StatefulWidget like this,
class MyOwnClass extends StatefulWidget {
State createState () => _MyOwnClassState();
}
And you have a State class for your StatefulWidget like this,
class _MyOwnClassState extends State<MyOwnClass> {
}
Now, State class is meant to house variables that tend to change in order for your UI to be rebuilt.
So you can have variables in your State that you can update using setState.
But what if you had some data that doesn't change and you want to avoid putting them inside the State class.
That's where your StatefulWidget comes to play.
You can store variables in your MyOwnClass and the widget variable inside the State class gives you a way to access them.
For example,
class MyOwnClass extends StatefulWidget {
int numberThatDoesntChange = 1;
State createState () => _MyOwnClassState();
}
You can access them in your State class like this,
class _MyOwnClassState extends State<MyOwnClass> {
Widget build(BuildContext context) {
return Text('$widget.numberThatDoesntChange');
}
}
Apart from this, your StatefulWidget has many more internal instance members that you can access inside of your State class using the widget variable.
The widget refers to the actual view that renders on the screen. It extends the StatefulWidget class of the flutter framework and overrides the createState() method. The createState() method is used to create the instance of state class. We will look into createState().
The state class is used to maintain the state of the widget so that it can be rebuilt again. It extends the State class of the flutter framework and overrides the build method.
The framework calls build() method again and again whenever setState() method is called. The setState() method notifies the framework that the internal state of this object has changed and it should be rebuilt. Suppose we change the value of text in StatefulWidget then we need to call setState().
Edit As Nisanth pointed outh in his comment - I missed your question completely; please ignore the below....
Let me try my answer, I don't think others are getting your point.
In your exapmle, Column(children: x) expect a list of Widgets.
You have two options - either provide this list directly:
class _MyOwnClassState extends State<MyOwnClass> {
#override
Widget build(BuildContext context) {
return ListTile(
title: Container(
child: Column(children: <Widget>[SomeWidget()]),
),
);
}
}
Or if you have more complex code that generates widget - based on input parameters, or you have the same widget generated multiple times and you want to avoid the code duplication - you would create the separate function to do the job.
Something like:
class _MyOwnClassState extends State<MyOwnClass> {
List<Widget> makeWidgetChildren(int param) {
/*
some very complex logic here
/*
if (param>3 && param<4) {
return List<Widget>.generate(4, (index)=>SomeWidget1(index));
} else {
return <Widget>[Center()];
}
}
#override
Widget build(BuildContext context) {
return ListTile(
title: Container(
child: Column(children: makeWidgetChildren(**widget.jsonObject)**),
),
);
}
}
So basically, it is just to make the code nicer; and to avoid having code repeated over and over again in the build function.
To start, I'm new to Flutter, so I am completely open to the possibility that my problem stems from a fundamental misunderstanding, but here is my question:
I am trying to get a good understanding of how to use Provider in conjunction with with the get_it package.
I think I understand how to use the Provider pattern in the standard case, by which I mean creating a unique class with a view and a view_model. Where I seem to have become lost is when I design a custom widget as a base template class and then extend that widget so that it can be tailored for use in a specific class view, I'm not seeing how to connect it to the Provider pattern because the base class doesn't know in advance which view_model it needs to listen to.
Below I will provide short example of what I am doing in the standard case, where things seem to work fine, and then I will show a short example of how I am trying to build the custom widget and extend it...
Here is the sample standard way in which I am using the Provider pattern with get_it, in which everything seems to work just fine:
class MyScreenView extends StatefulWidget{
#override
_ProfileEditScreenViewState createState() => _ProfileEditScreenViewState();
}
class _MyScreenViewState extends State<MyScreenView>{
final MyScreenViewModel model = serviceLocator<MyScreenViewModel>();
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<MyScreenViewModel>(
create: (context) => model,
child: Material(
color: Colors.white,
child: Consumer<MyScreenViewModel>(
builder: (context,model,child) => Text(model.someText),
),
),
);
}
}
class MyScreenViewModel extends ChangeNotifier{
String? _someText;
MyScreenViewModel() {
this._someText= 'Sample Text';
}
String get someText=> _someText;
set someText(String value) {
_someText= value;
notifyListeners();
}
}
Here is an example of how I am trying to build a base class, but am uncertain as to how I go about connecting it to Provider: (The idea here is that the below widget would be part of a more complex widget that would have a view_model where the state for the overall widget would be maintained)
class BaseCheckBoxTile extends StatefulWidget{
bool isChecked;
Function(bool) checkBoxOnChanged;
BaseCheckBoxTile({this.isChecked = false, required this.checkBoxOnChanged});
#override
_BaseCheckBoxTileState createState() => _BaseCheckBoxTileState();
}
class _BaseCheckBoxTileState extends State<BaseCheckBoxTile>{
#override
Widget build(BuildContext context) {
return SizedBox(
child: Checkbox(value: widget.isChecked,onChanged: widget.checkBoxOnChanged,),
);
}
}
class CustomCheckBoxTile extends BaseCheckBoxTile{
bool isChecked;
Function(bool) checkBoxOnChanged;
CustomCheckBoxTile({this.isChecked =false, required this.checkBoxOnChanged})
:super(isChecked: isChecked, checkBoxOnChanged: checkBoxOnChanged);
}
My instinct is to want to put something in my _BaseCheckBoxTileState that gives me access to the larger widget's view_model, like what I do in the first example with:
"MyScreenViewModel model = serviceLocator<MyScreenViewModel>(); "
If I had that, then I could assign the values in my _BaseCheckBoxTileState by referring to the model instead of widget (e.g., model.isChecked instead of widget.isChecked). The model would obviously extend ChangeNotifier, and the view that is making use of the custom widget would wrap the widget in a Consumer. However, the _BaseCheckBoxTileState doesn't know what view_model to listen to.
Would I accomplish this by putting some generic Type or Object in for my View_Model which could be assigned when the class is built? Or am I approaching this in a completely wrong way?
I have a screen in my Flutter app that contains a pageview. In that pageview are four stateful widgets. I need to be able to access the members of the first three widgets so I can get the data from them, bring it into the main screen class, and send it to the fourth widget. Below is a model of what I'm trying to accomplish.
I'm thinking that I can do this with methods in each widget's state class but when I create a method there, I can't access it anywhere else even if it's public.
An example of one of the widgets:
import 'package:flutter/material.dart';
class WidgetSample extends StatefulWidget {
#override
_WidgetSampleState createState() => _WidgetSampleState();
}
class _WidgetSampleState extends State<WidgetSample> {
TextEditingController _sampleController = new TextEditingController();
//I want to access this method through an instance of the WidgetSample class
String getTextFromField(){
return _sampleController.text;
}
#override
Widget build(BuildContext context) {
return Container(
child: TextField(
controller: _sampleController,
),
);
}
}
I have tried creating a copy of the method in the widget sample class that calls the method in the state class but that hasn't worked.
Any help would be appreciated. Thanks in advance!
Edit: I have found an answer to my problem provided by BambinoUA on this post:
Controlling State from outside of a StatefulWidget
I currently have many problems in my app with the get package for Flutter (https://pub.dev/packages/get) and the following state scenario:
For example I have a GetxController UserController. I need this controller in different Widgets, so I initialize it with Get.put() in the first widget and for the other child widgets I'll call it with Get.find(). That works.
But: I have some widgets that sometimes load before the controller got initialized and sometimes after. So I get many "UsersController" not found errors. Maybe there exists some workaround for this problem?
You could initialize your UsersController class using a Bindings class, prior to the start of your app.
Example
class UsersController extends GetxController {
static UsersController get i => Get.find();
int userId = 5;
}
class UsersBinding extends Bindings {
#override
void dependencies() {
Get.put<UsersController>(UsersController());
}
}
void main() async {
UsersBinding().dependencies();
runApp(MyApp());
}
Done this way your UsersController is guaranteed to be available everywhere in your app, prior to any Widgets loading.
class MyHomePage extends StatelessWidget {
final UsersController uc = Get.find();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('GetX Bindings'),
),
body: Center(
child: Obx(() => Text('userId: ${uc.userId}')),
),
);
}
}
try to add
GetMaterialApp(
smartManagement: SmartManagement.keepFactory,
)
so that it can store factory of those instanse
or make sure add permanent
Get.put<Repo>(Repo(), permanent: true);
so that it never get deleted from memory
if u need to check class is initialized, u most keep the class in memory with permanent:trueand set tag:'anything you want for check this object' property in Get.put function, and now u can check
bool Get.isRegistered<className>(tag: 'TagInPut')
If there's no specific reason, you can just call Get.put(UserController()) at main function and wrap material app with GetMaterialApp.
if you are using get to provide an instance of something across your app
meaby https://pub.dev/packages/get_it could help you more. just be sure that you use allowReassignment==true so you can update your instance if you want save a full new controller, but if you want to use the same always get_it is perfect for you