How to access a controller from multiple screens - flutter - flutter

Let's say I created a ScrollController in a statefullWidget like so:
late ScrollController controller;
#override
void initState() {
super.initState();
controller = ScrollController();
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
Using this controller indside the widget is easy.
But, if I want to access that controller from another screen, I have to pass it as a parameter maybe like so:
Navigator.pushNamed(context, '/another-screen', arguments: controller);
But, What if the screens are totally independent? (I can't pass it as an argument) I thought of using Provider to globally provide the controller. But now, I can't dispose it.

try to add on global late ScrollController controller;
and then initialise that variable
you can declare on main.dart late ScrollController controller;

Related

Call api after bage build in getx

Im using getx and i want to call api after bage build, because this api its not necessary part of the page build.. What i know is this way
#override
void initState(){
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_){
});
}
But what about getx best way ?
the Getx package offers lifecycle methods that are very convenient in you're cases, what you need here is to use the onReady(), which is called one frame after the onInit() is executed, you can say that its equivalent to the:
#override
void initState(){
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_){
// Here is the code which will be executed exactly after initState using StatefulWidget
});
}
you can use onReady() like this:
class TextController extends GetxController {
#override
void onInit() {
/*...*/
}
void onReady() {
// Here is the code which will be executed exactly after onInit using Getx
}
}

Reinitialize Getx scrollController when navigate to same page

I use Get.offNamed to navigate to same page _ but this method called
#override
void onClose() {
scrollController.removeListener(_loadData);
super.onClose();
}
As a result I lose page scrolling How do I reset the scrollController
the Controller :
class PostsController extends GetxController with StateMixin<Posts> {
ScrollController scrollController = ScrollController();
#override
void onInit() {
_getData();
scrollController = ScrollController()..addListener(_loadMore);
super.onInit();
}
_getData() async {}
_loadMore() async {}
#override
void onClose() {
scrollController.removeListener(_loadMore);
super.onClose();
}
}
---I noticed Get.offNamed at first it reads the Controller of new page (in my case it's the same page)
[GETX] Instance "PostsController" has been created
[GETX] Instance "PostsController" has been initialized
Then deletes the controller of old page (in my case it's the same page)
[GETX] "PostsController" onDelete() called
[GETX] "PostsController" deleted from memory
Because of working in this order, the scrollController is lost. If it works the other way around the scrollController will be reinitialized.
I don't know how to go to the same page after deleting the controller (Firstly) and reinitializing it (secondly), or not calling onClose() when going to the same page as replacment
You can try initializing your scroll controller in the initstate like this:
class PostsController extends GetxController with StateMixin<Posts> {
late final ScrollController scrollController;
#override
void onInit() {
_getData();
scrollController = ScrollController()..addListener(_loadMore);
super.onInit();
}
_getData() async {}
_loadMore() async {}
#override
void onClose() {
scrollController.removeListener(_loadMore);
super.onClose();
}
}

the difference between initialize controller in initState and without

I see people usually initialize the controller like this, initializing it in initState() method.
late VideoPlayerController _videoPlayerController;
#override
void initState() {
super.initState();
_videoPlayerController = VideoPlayerController.network(
"https://assets.mixkit.co/videos/preview/mixkit-spinning-around-the-earth-29351-large.mp4");
}
but then I realize if I just put the controller like this without initState()just put the controller after the variables with late in before the variables, everything works fine. So what is the difference?
class _VideoDetailScreenState extends State<VideoDetailScreen> {
late VideoPlayerController _videoPlayerController = VideoPlayerController.network(
"https://assets.mixkit.co/videos/preview/mixkit-spinning-around-the-earth-29351-large.mp4");
As from the official documentation:
The framework calls initState. Subclasses of State should override initState to perform one-time initialization that depends on the BuildContext or the widget, which are available as the context and widget properties, respectively, when the initState method is called.

I am trying to use tab controller in flutter how can I access it inside the build context

I am trying to use a tab bar controller , what is the right way to add it
Just declare the tabController globally inside your state class and initialise it inside init state as you did, then you can access it inside your build method.
late TabController tabController;
void initState(){
tabController=TabController(vsync:this,length:3);
}
now use accordingly tab controller inside build method.
Try to declare tabController globally inside your state class and init it inside init state see the documentation for more details :
class _JobApplication... extendes State<...> ..{
late TabController _tabController;
#override
void initState() {
super.initState();
_tabController = TabController(vsync: this, length: 3);
}
}
declare in state
late TabController _tabController;
Assign in initstate
#override
void initState() {
super.initState();
_tabController = TabController(vsync: this, length: 3);
}

Why are the variables in initState not acessible?

I want to create a TextController in the initState and then dispose of it like a good boy in dispose. But for some reason, the controller is not avaiable outside of the intiState:
class _InputFieldEnterThingState extends State<InputFieldEnterThing> {
#override
void initState() {
TextEditingController textController =
TextEditingController(text: 'placeholder');
super.initState();
}
#override
void dispose() {
textController.dispose();
super.dispose();
}
It tells me "textController" is not defined in dispose() ... same, if I try using it in the build method. It's, as if the varialbe is strictly local in initState. I feel I'm missing something super obvious, but cannot find it.
The textController is a local variable in the initState method, you need to make him global and the dispose method will recognize him.
The way to do that:
class _InputFieldEnterThingState extends State<InputFieldEnterThing> {
TextEditingController textController; // make him global
#override
void initState() {
textController = // without redefine
TextEditingController(text: 'placeholder');
super.initState();
}
#override
void dispose() {
textController.dispose();
super.dispose();
}
Since you declared the variable textController inside initState the variable is only accessible in initState. If you want to access textController e.g. in dispose, you have to declare it outside the initState.
class _InputFieldEnterThingState extends State<InputFieldEnterThing> {
late TextEditingController textController;
#override
void initState() {
textController = TextEditingController(text: 'placeholder');
super.initState();
}
#override
void dispose() {
textController.dispose();
super.dispose();
}