initState() taking too long to load - flutter

I have home screen which two tabs. now when I get to home tab and got to search instantly. I get red screen for slight second and then all widgets get loaded.
Now where problem is,
in initState() I'm assigning store.filteredPOI to widget.floorPlan.pois.
I'm getting store.filteredPOI from a network call which will take some time. so in that fraction of time widget.floorPlan is null so how can I show a loader to prevent the red error screen,
code
class SearchTab extends StatefulWidget {
final FloorPlan floorPlan;
final bool isIndoorMapVisible;
final NetworkStatus networkStatus;
SearchTab({this.floorPlan, this.isIndoorMapVisible,this.networkStatus});
#override
_SearchTabState createState() => _SearchTabState();
}
class _SearchTabState extends State<SearchTab> {
final TextEditingController textController = TextEditingController();
SearchStore store;
#override
void initState() {
store = SearchStore();
store.filteredPOI = widget.floorPlan.pois; //<<<<<<<<
super.initState();
}
#override
Widget build(BuildContext context) {
return (...)

what I ended up doing was add the operation inside built method
#override
Widget build(BuildContext context) {
store.filteredPOI = widget.floorPlan.pois;
return (...)

Related

Create / Manage dynamic TextEditingControllers

I got a ListView.builder that generates n number of elements and I am looking at adding a controller for each of them. I have seen some approaches of adding a controller to a list of controllers and then access them by the index however I am just wondering how will this impact the performance of the screen if lets say you have 20 controllers? Are there some best practices for this scenario? Should you even go down this line or avoid it?
I suggest to introduce a Widget for all items in list.
Make sure you dispose in a correct place for the performance.
Also I request to store the user entered value with the object of item will help to restore on scrolls.
Eg:
class YourWidget extends StatefulWidget {
const YourWidget({Key? key, required this.item}) : super(key: key);
final YourItem item;
#override
State<YourWidget> createState() => _YourWidgetState();
}
class _YourWidgetState extends State<YourWidget> {
final controller = TextEditingController();
#override
void initState() {
super.initState();
controller.text = widget.item.enteredValue;
}
#override
Widget build(BuildContext context) {
return TextField(
controller: controller,
onChanged: (value){
widget.item.enteredValue = value;
},
...
);
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
}
class YourItem {
String? id;
...
String enteredValue = '';
}

How can I use initState in a widget build to reference the value of riverpod?

I want to assign the value of currentUser.profilepictureURL to ListImage.
But if I put the initState outside of the widget build, it will be out of scope. Please tell me.
class _MyHomePageState extends ConsumerState<MyHomePage> {
var listImage = [];
#override
Widget build(BuildContext context) {
final currentUser = ref.watch(userModelProvider);
void initState() {
listImage.add(currentUser.profilePictureURL);
super.initState();
}
return Container();
}
}
The way your are using initState is wrong. InitState is an #override and it should not to be used inside a build method.
try this:
class _MyHomePageState extends ConsumerState<MyHomePage> {
var listImage = [];
#override
Widget build(BuildContext context) {
final currentUser = ref.watch(userModelProvider);
listImage.add(currentUser.profilePictureURL);
return Container();
}
}

how to get id sent with a Screen in flutter

i send an idd from another screen when i want to navigate to this WaitingScreen
Now when i want to use the idd , I get an error in the line
FirebaseFirestore.instance.collection('ambulance').doc(idd).get()
class WaitingScreen extends StatefulWidget {
final String idd;
String? Key;
WaitingScreen({required this.idd}) : super();
_WaitingScreenState createState () => _WaitingScreenState( ) ;
}
class _WaitingScreenState extends State<WaitingScreen> with SingleTickerProviderStateMixin{
late AnimationController _controller;
#override
void initState() {
super.initState();
_controller =
AnimationController(vsync: this, duration: Duration(minutes: 5));
_controller.forward();
}
#override
Widget build(BuildContext context) {
String? valuee;
return FutureBuilder<DocumentSnapshot>(
future: FirebaseFirestore.instance.collection('ambulance').doc(idd).get(),
When using a stateful widget, you need to reference variables on the widget itself by using the following construction:
widget.idd
By using the prefix widget., you make sure to access the variables on the widget, and not on the state you are in.

How to setState() and not rebuild tabs in a TabBarView

I have this problem, i have a home page where it has tabs. I like when i switch tabs to make the TabBar show black the tab that is selected and also i want to change the color of the whole Scaffold. So i made also a custom controller and used it like this:
TabController _controller;
#override
void initState() {
super.initState();
_controller = TabController(vsync: this, length: 5);
_controller.index = 1;
_controller.addListener(() {
if (!_controller.indexIsChanging) {
setState(() {
scaffoldColor = colors[_controller.index];
});
}
});
}
The thing is that in this way all of my tabs are going to be rebuild and this is very bad because i have heavy tasks in few of them.
I also have used AutomaticKeepAliveClientMixin in all of the tabs but it didn't fix the problem. By the way i used it like this:
class Tab1 extends StatefulWidget {
#override
_Tab1State createState() => _Tab1State();
}
class _Tab1State extends State<Tab1> with AutomaticKeepAliveClientMixin {
#override
Widget build(BuildContext context) {
super.build(context);
print("Tab 1 Has been built");
return Text("TAB 1");
}
#override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
}
If for heavy tasks you mean a Future, you should place it inside initState.
See this answer: How to load async Stream only one time in Flutter?.

flutter - clear the widget cache

When I leave a page when I work with flutter and then re-enter it, the old values are saved.
I don't want this to happen.
For example, when I first enter:
int number = 1;
class TestPage extends StatefulWidget {
#override
_TestPageState createState() => _TestPageState();
}
bool donus = true;
class _TestPageState extends State<TestPage> {
List<Todo> sorular = new List<Todo>();
#override
void initState() {
print(donus);
super.initState();
getTodos();
}
bool pressAttention = true;
String ileri = "İleri", geri = "Geri";
#override
Widget build(BuildContext context) {number++;
print(number);
output:1
Second entry to the page:
output:2
I do not know how to fix this.
The scope of your number variable is outside the scope of your page and its state.
number is essentially static or global, and its lifetime is tied to your application's. Tighten up its scope so that it is declared within your state class and initialise it in your initState method (for private non-final variables).
class TestPage extends StatefulWidget {
#override
_TestPageState createState() => _TestPageState();
}
bool donus = true;
class _TestPageState extends State<TestPage> {
List<Todo> sorular = new List<Todo>();
int _number;
#override
void initState() {
_number = 1;
print(donus);
super.initState();
getTodos();
}
bool pressAttention = true;
String ileri = "İleri", geri = "Geri";
#override
Widget build(BuildContext context) {
_number++; // You probably don't want to increment every time you build,
// but I have no idea what you're using `number` for.
print(_number);
Your donus variable is also global, which is unlikely to be what you had intended. Dart is an object-oriented language; refer to the language tour for more details on classes, scope, etc.