Flutter Provider is returning null in initState() - flutter

I am getting List of DropdownMenuItem from firebase with stream using provider if I use provider in build it doesn't return null works great but in initstate even if I am setting the listen value false returns null.
Here is the code:
List<DropdownMenuItem<category.List>> dropdownmenuoptions;
DropdownMenuItem<category.List> dropdownMenuItem;
String dropDownValue;
#override
void initState() {
dropdownmenuoptions = Provider.of<List<DropdownMenuItem<category.List>>>(
context,
listen: false);
dropdownMenuItem = dropdownmenuoptions.first;
dropDownValue = dropdownMenuItem.value.name;
super.initState();
}
Here is the error message:
The following NoSuchMethodError was thrown building Builder:
The getter 'first' was called on null.
Receiver: null
Tried calling: first
The relevant error-causing widget was
MaterialApp
lib/main.dart:37
When the exception was thrown, this was the stack
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
#1 _HomeScreenState.initState
package:tobetter/…/home/home_screen.dart:73
#2 StatefulElement._firstBuild
package:flutter/…/widgets/framework.dart:4833
#3 ComponentElement.mount
package:flutter/…/widgets/framework.dart:4649
... Normal element mounting (24 frames)

The direct context inside initState can't be used for everything and specialty with Provider . so, as a solution use didChangeDependencies instead , example:
#override
void didChangeDependencies() {
super.didChangeDependencies();
dropdownmenuoptions = Provider.of<List<DropdownMenuItem<category.List>>>(
context,
listen: false);
dropdownMenuItem = dropdownmenuoptions.first;
dropDownValue = dropdownMenuItem.value.name;
}
if you really need it inside your initState you can use it inside addPostFrameCallback
#override
void initState(){
...
SchedulerBinding.instance.addPostFrameCallback((_) {
dropdownmenuoptions = Provider.of<List<DropdownMenuItem<category.List>>>(
context,
listen: false);
dropdownMenuItem = dropdownmenuoptions.first;
dropDownValue = dropdownMenuItem.value.name;
}
});

Related

Unhandled Exception: setState() called after dispose() with Firebase Realtime Database chat feature

I am receiving this error:
[VERBOSE-2:dart_vm_initializer.cc(41)] Unhandled Exception: setState() called after dispose(): _EventChatScreenState#7c8b5(lifecycle state: defunct, not mounted)
This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().
#0 State.setState.<anonymous closure> (package:flutter/src/wid<…>
However, the only place I am calling setState is in the initState:
#override
void initState() {
super.initState();
dbRef = dbInstance.ref("/events/");
var query = dbRef!.child(widget.event.event.eventId);
FirebaseList(
query: query,
onChildAdded: (index, snapshot) {
Map<dynamic, dynamic> childMap = snapshot.value as dynamic;
ChatMessage newChatMessage = ChatMessage(
chatMessageId: snapshot.key.toString(),
userId: childMap["userId"],
displayName: childMap["displayName"],
message: childMap["message"],
datetime: childMap["datetime"],
);
setState(() {
chatMessages.add(newChatMessage);
});
},
);
_messageFieldController = TextEditingController();
}
#override
void dispose() {
super.dispose();
_messageFieldController.dispose();
}
I'm not really sure why this is happening, but I included the dispose method since it the error references it.
Worth noting that I am doing this to make the screen scroll to the bottom of the chat messages which are display using a ListView.builder
void scrollToBottom() {
SchedulerBinding.instance.addPostFrameCallback((_) {
_scrollController.jumpTo(_scrollController.position.maxScrollExtent);
});
}
#override
Widget build(BuildContext context) {
final user = ref.watch(userProvider);
if (chatMessages.isNotEmpty) {
scrollToBottom();
}
If I remove the above code the issue seems to go away
instead of this
#override
void dispose() {
super.dispose();
_messageFieldController.dispose();
}
try this
#override
void dispose() {
_messageFieldController.dispose();
super.dispose();
}

Method 'dispose' was called on null. Receiver: null Tried calling: dispose()) - Push.Navigator

I added in last page of my app a button to move back to the previous page - expecting to refresh the complete app or page.
context,
MaterialPageRoute(builder: (context) => SplashPage()), // this mymainpage is your page to refresh
(Route<dynamic> route) => false,
);
I receive the below error message when pressed.
═══════ Exception caught by widgets library ═══════════════════════════════════
The method 'dispose' was called on null.
Receiver: null
Tried calling: dispose()
════════════════════════════════════════════════════════════════════════════════
What do I need to place in the Dispose widget to avoid calling null.
DateFormat format = DateFormat('dd/MM');
List<bool> flips = [false, false, false, false];
List tarots = [];
List unLockCard = [];
BannerAd _bannerAd;
#override
void dispose() {
_bannerAd.dispose();
super.dispose();
}
I looked into this solution Dispose widget when navigating to new route but can not apply.
There may be a situation that the banner has not loaded so tying to dispose it when its null will throw an error. You can add a condition check before you dispose
#override
void dispose() {
if(_bannerAd != null)
{
_bannerAd.dispose();
}
super.dispose();
}
if you are using null safety you can declare banner ad like
BannerAd? _bannerAd;
and dispose it like
_bannerAd?.dispose();

Flutter: Provider shows Exception but app run fine while using default listen:true

I'm Using provider in initState() to call the api but if I use listen:false then it does not update UI and it always shows me loader but if I use listen:true then app works fine but in the terminal it shows me exception and tells me write listen:false.
My UI,
class ChopperNewsCard extends StatefulWidget {
#override
_ChopperNewsCardState createState() => _ChopperNewsCardState();
}
class _ChopperNewsCardState extends State<ChopperNewsCard> {
ScrollController scrollController = ScrollController();
int currentPage = 5;
ChopperApiStore _apiStore = ChopperApiStore();
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
_apiStore = Provider.of<ChopperApiStore>(context,);//<--- here it tells me to write listen:false
});
_apiStore.getResponse(currentPage);
scrollController.addListener(() {
if (scrollController.position.pixels ==
scrollController.position.maxScrollExtent) {
if (currentPage < 20) {
currentPage = currentPage + 5;
_apiStore.getResponse(currentPage);
}
}
});
}
#override
void dispose() {
scrollController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
var height = MediaQuery.of(context).size.height;
var width = MediaQuery.of(context).size.width;
return Observer(builder: (context) {
return Container(
height: height * 0.37,
width: double.infinity,
child: _apiStore.res.articles == null
? CircularProgressIndicator()
: ListView.builder(...),
);
});
}
}
api calling class,
class ChopperApiStore extends _ChopperApiStore with _$ChopperApiStore{}
abstract class _ChopperApiStore with Store{
ApiCall apiCall = ApiCall();
#observable
ChopperNews res = ChopperNews();
#action
Future<void> getResponse(int page) async {
var data = await apiCall.getNews(page);
res = data;
}
}
the error I'm getting,
======== Exception caught by scheduler library =====================================================
The following assertion was thrown during a scheduler callback:
Tried to listen to a value exposed with provider, from outside of the widget tree.
This is likely caused by an event handler (like a button's onPressed) that called
Provider.of without passing `listen: false`.
To fix, write:
Provider.of<ChopperApiStore>(context, listen: false);
It is unsupported because may pointlessly rebuild the widget associated to the
event handler, when the widget tree doesn't care about the value.
The context used was: ChopperNewsCard(dependencies: [MediaQuery], state: _ChopperNewsCardState#8f6cd)
'package:provider/src/provider.dart':
Failed assertion: line 262 pos 7: 'context.owner.debugBuilding ||
listen == false ||
debugIsInInheritedProviderUpdate'
When the exception was thrown, this was the stack:
#2 Provider.of (package:provider/src/provider.dart:262:7)
#3 _ChopperNewsCardState.initState.<anonymous closure> (package:fruitley/week-5/bonus/chopper/widgets/chopper_news_card.dart:32:28)
#4 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1117:15)
#5 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1063:9)
#6 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:971:5)
...
I think if you want to use listen:true to have the build method called you are suppose to override didChangeDependencies rather then initState Checkout this article it might help https://medium.com/swlh/flutter-provider-and-didchangedependencies-15678f502262
ok I'm dumb. I didn't even need to use addPostFrameCallback.
I just removed it and if I want to use provider outside of widget tree that I must use listen:false as it was showing in the exception so now everything makes sense.

Provider : Looking up a deactivated widget's ancestor is unsafe

Trying to get the value from provider, it works OK, but I get the error below. What i am doing wrong here?
#override
Widget build(BuildContext context) {
String route = Provider.of<User>(context) == null ? Router.LOGIN : Router.HOME;
Future.delayed(const Duration(seconds: 2), () => Navigator.pushReplacementNamed(context, route));
return Scaffold(........
error
E/flutter (23058): [ERROR:flutter/shell/common/shell.cc(209)] Dart Error: Unhandled exception:
E/flutter (23058): Looking up a deactivated widget's ancestor is unsafe.
E/flutter (23058): At this point the state of the widget's element tree is no longer stable.
E/flutter (23058): To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.
The problem is not being able to await the navigator call. If you need to navigate to the correct page on build, then create an async method with no return type, then call the method in initState.
_checkUserExistsAndNavigate() async {
String route = Provider.of<User>(context) == null ? Router.login : Router.home;
await Future.delayed(seconds: 2), () => Navigator.pushReplacementNamed(context, route);
}
#initState(() {
_checkUserExistsAndNavigate();
super.initState();
}

StreamBuilder<FileSystemEntity>(dirty, state: _StreamBuilderBaseState<FileSystemEntity, AsyncSnapshot<FileSystemEntity>>#25d1b)

I have got an error while working with Stream builders.
In my code, I used if(snapshot.data != null) { list.add(snapshot.data); } but I m getting a msg that add was called on null. I even added print('') statement to check if snapshot.data is null, but it is working fine with print() too. So I m not at all understanding how to solve this error. Someone please respond. Thanks in advance.
Here is my code
class Wrapper extends StatefulWidget {
#override
_WrapperState createState() => _WrapperState();
}
class _WrapperState extends State<Wrapper> {
Stream<FileSystemEntity> mystream;
var _directory;
void getfilesdata() async
{
_directory = await getApplicationDocumentsDirectory();
await Directory('${_directory.path}/data').create(recursive: true);
mystream = Directory('${_directory.path}/data').list().map((data) => data);
await Directory('${_directory.path}/documents').create(recursive: true);
}
#override
void initState() {
super.initState();
getfilesdata();
}
#override
Widget build(BuildContext context) {
List<FileSystemEntity> alldata;
return StreamBuilder<FileSystemEntity>(
stream: mystream,
builder: (context, snapshot) {
if(!snapshot.hasData)
{
print('No data yet');
return Loading();
}
else
{
if(snapshot.data != null && !snapshot.hasError)
{
print(snapshot.data);
alldata.add(snapshot.data);
}
if(snapshot.connectionState==ConnectionState.done)
{
return HomeScreen(alldata: alldata);
}
else return Loading();
}
}
);
}
}
And this is the result:
Performing hot restart...
Syncing files to device ZUK Z2132...
Restarted application in 1,734ms.
I/flutter (11840): No data yet
I/flutter (11840): No data yet
I/flutter (11840): File: '/data/user/0/com.example.easyscan/app_flutter/data/data[0]'
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following NoSuchMethodError was thrown building StreamBuilder<FileSystemEntity>(dirty, state: _StreamBuilderBaseState<FileSystemEntity, AsyncSnapshot<FileSystemEntity>>#25d1b):
The method 'add' was called on null.
Receiver: null
Tried calling: add(Instance of '_File')
The relevant error-causing widget was:
StreamBuilder<FileSystemEntity> file:///home/praneeth/AndroidStudioProjects/easyscan/lib/wrapper.dart:40:12
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1 _WrapperState.build.<anonymous closure> (package:easyscan/wrapper.dart:53:25)
#2 StreamBuilder.build (package:flutter/src/widgets/async.dart:509:81)
#3 _StreamBuilderBaseState.build (package:flutter/src/widgets/async.dart:127:48)
#4 StatefulElement.build (package:flutter/src/widgets/framework.dart:4619:28)
...
════════════════════════════════════════════════════════════════════════════════════════════════════
Your error is because allData is null so you cannot call the add() method.
You can declare your variable as follow:
List<FileSystemEntity> alldata = [];
By doing this allData will be initialized as an empty list and you will be able to call its methods.