I have a class which has variables like this:
class MyDragTarget extends StatefulWidget {
final String assetImage;
final String name;
MyDragTarget(this.name, this.assetImage);
}
EDIT: Sorry for wrong code below. I knew how to use widget.name to get name of the parent. But how can i get name of other class.
Should i use InheritedWidget? To use InheritedWidget must i learn Provider?
I want to access the name and assetImage of MyDragTarget in another class such as:
class Another extends StatefulWidget {
print(MyDragTarget.name);
}
You can use widget.name. For example, if you are trying to access assetImage you can use print('${widget.assetImage}'); Just a side note, this is to access the variables in your StatefulWidget. You can't do it for any class.
you can get using widget
widget.assetImage
wiget.name
print('${wiget.name}');
if you want to use in its create State class, you can access it via widget.assetImage Like
class _MyDragPlayerState extends State<MyDragPlayer> {
...
// print('${widget.assetImage }');
...
}
but if you want to access in other classes than this you can declare variables as static like
class MyDragTarget extends StatefulWidget {
static String assetImage;
static String name;
MyDragTarget(this.name, this.assetImage);
#override
_MyDragTargetState createState() => _MyDragTargetState();
}
and then in other class you can access via
class OtherClass{
...
// print('${MyDragTarget.assetImage }');
...
}
check for null safety first, also read about pros and cons of using static variables.
Related
createState:
Creates the mutable state for this widget at a given location in the tree.
https://api.flutter.dev/flutter/widgets/StatefulWidget/createState.html
Now, in code:
class A extends StatefulWidget {
#override
_AState createState() => _AState();
}
class _AState extends State<A> {
}
Here we create a separate class named _AState which inherits from a predefined class named State?
So, what is createState' role here? How does it create a mutable state for us?
With createState you tell the StatefulWidget which class to use as state for this widget. And you tell it here that it needs to create an instance of _AState for this widget.
By the way, it is also recommended to write it as
State<A> createState() => _AState();
It still works the way you wrote it but the IDE might complain about
Avoid using private types in public APIs
Saying the return type is State<A> instead of _AState removes this warning.
In order to create a stateful widget in a flutter, it uses the createState() method. Stateful Widget means a widget that has a mutable state.
I have a situation where I want to create multiple flutter StatefulWidgets based on the same state class. The problem I run into seems clear, the state widget needs to know the properties of the parent that calls createState. There has to be a way to accomplish this without having to copy paste large amounts of code.
What I have so far is a state class that looks like this:
abstract class XxxState<T extends StatefulWidget> extends State<T>
{ TextEditingController textController; // instantiated by initState().
}
to accomplish what I want I create several abstract methods that the subclass will override to implement it's function. The problem is when I create the class I want to instantiate I don't know how to connect the new StatelessWidget to the state class that overrides the XxxState class.
class YyyWidget extends StatefulWidget {
#override
_YyyState createState() => _YyyState();
}
class _YyyState<YyyWidget> extends XxxState {
/// In this class widget.xxx looks to StatefulWidget and not YyyWidget
}
Any reference for how this should be done would be appreciated.
All one has to do is learn how to subclass a StatefulWidget correctly and all works as expected.
abstract class YyyWidget extends StatefulWidget { ... }
// Do not do the createState here
// Someone edited the question and removed the abstract from the code,
// thereby changing the question to one they thought they could answer.
Then create the abstract state
abstract class YyyState<Page extends XxxWidget>
extends State<Page> {
{
TextEditingController textController;
...
}
Then the subclass calls
class ZzzWidget extends XxxWidget {
// Do the create state here
#override
_AaaState createState() => _AaaState();
}
and the subclass state is
class _AaaState extends YyyState<AaaWidget> {
//inside this class widget.field gets state from AaaWidget
}
I don't even remember what the original post was, So maybe deleting the question is the better option here.
Context
I come from Redux and I am learning the BLoC pattern for global state management. I am having troubles defining where should I store values as properties inside the BLoC class, and when I should store values inside States.
Use case
I have a home page where I show some Ads, depending on its category (category should never be null). I implemented an AdsBloc like this:
class AdsBloc extends Bloc<AdsEvent, AdsState> {
final AdsRepository repository;
AdsBloc({#required this.repository})
: super(AdsInitial(category: Category.DOGS));
#override
Stream<AdsState> mapEventToState(
AdsEvent event,
) async* {
// my code
}
}
And these are my AdsState:
abstract class AdsState {
final Category category;
AdsState({this.category});
}
class AdsInitial extends AdsState {
AdsInitial({category}) : super(category: category);
}
class AdsSuccess extends AdsState {
final PaginatedAds paginatedAds;
AdsSuccess({this.paginatedAds, category}) : super(category: category);
}
class AdsFailure extends AdsState {
AdsFailure({category}) : super(category: category);
}
Problem
Because of the way I implemented the pattern, I need to pass the category every time I change the state.
Solution?
So I was thinking if I can consider the category property to be of AdsBloc and remove it from state, this way I can get a better control of this property.
Implement "category" as a parameter for the event that is triggering ad loading process. This way, for example, you will tell BLoC to "LoadAds" with "category: Category.DOGS".
class LoadAds extends AdsEvent {
final Category category;
LoadAds({
#required this.category,
});
#override
List<Object> get props => [category];
}
This way you will be able to use single bloc instance to load different ad types when needed. Load DOGS first, 2 minutes later load CATS instead of dogs.
If you do not need this ability - then defining category inside bloc itself is perfectly fine.
I am passing variables from one activity to another in flutter but getting the error "Instance member ‘latitude’ can’t be accessed using static access" I need it converted in that block so I can assign it to a static URL.
class Xsecond extends StatefulWidget {
final double latitude;
final double longitude;
Xsecond(this.latitude, this.longitude, {Key key}): super(key: key);
#override
_Xsecond createState() => _Xsecond();
}
class _Xsecond extends State<Xsecond> {
static String lat = Xsecond.latitude.toString(); // Error: Instance member ‘latitude’ can’t be accessed using static access
...
followed by
...
String url = 'https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${lat},$lng&radius=$radius&type=restaurant&key=$api';
...
In your code both latitude and longitude are defined as non-static i.e. are instance variables. Which means they can only be called using a class instance.
class _Xsecond extends State<Xsecond> {
final xsecond = Xsecond();
static String lat = xsecond.latitude.toString();
...
Please read the basics of any Object Oriented Programming language e.g. Dart, java, C++
However, in your context the first class is your StatefullWidget. So you can access that by the widget field of your state class.
FIX:
class _Xsecond extends State<Xsecond> {
static String lat = widget.latitude.toString();
...
This error occurs if you use non-static variable like static. Let's take a look at this example:
class MyPage extends StatefulWidget {
final foo = Foo();
// ...
}
class _MyPageState extends State<MyPage> {
final newFoo = MyPage.foo; // Error
// ...
}
MyPage.foo isn't a static member but you are using if it was.
To solve this issue, you can either make the variable static
static final foo = Foo();
or
Use widget variable to get hold of the underlying variable.
class _MyPageState extends State<MyPage> {
#override
void initState() {
super.initState();
final newFoo = widget.foo; // No Error
}
// ...
}
I have an object that has static constant which I need to reach from its instance.
class ChatsScreen extends StatefulWidget {
var arguments;
static const name = ADatas.chatRoute;
ChatsScreen(this.arguments);
createState() => ChatsScreenState();
}
In above class' State object, I want to call static const name. Above class' State object's code:
class ChatsScreenState extends State<ChatsScreen> with RouteHelper{
String userName = "";
var textEditingController = TextEditingController();
#override
void initState() {
getRouteName(widget); //=> as I understand and see on the VSCode, its the ChatsScreen object.
super.initState();
}
}
I'm trying to implement an interface so I don't know the actually class name while writing the interface. And I thought that I can reach its static constant if I know its actual class. And I wrote something like this but it seems not to be possible. I guess I have a misunderstanding.
class RouteHelper{
String getRouteName(dynamic instance){
if(instance is StatefulWidget){
return instance.runtimeType.name; // => !!!
}
}
}
Note: I'm not trying to get the route name in actual. It's just a concept that i used in this question, so please don't refer better way to get the route name in flutter.
You can't do it like that, people have talked about this in this issue.
However you can kinda do it using class members and typing system.
abstract class Routed {
String getClassRoute();
}
class ChatsScreen extends StatefulWidget implements Routed {
var arguments;
static const name = "myexampleroutename";
ChatsScreen(this.arguments);
createState() => ChatsScreenState();
#override
String getClassRoute() {
return ChatsScreen.name;
}
}
class RouteHelper {
String getRouteName(Routed instance) {
return instance.getClassRoute();
}
}
I said you can't, but with dart:mirrors it is possible, however it is banned on Flutter packages. There is reflectable package that tries to fix that using code generation, but I am not aware of it's status/reliability.