gamelist is a String List of document names in the collection. The questionMap value is an array named "text" field obtained from the firestore document using the gamelist value as key. I would like to update the questionMap when I press the pass button, When I press the pass button, I see that the questionMap is indeed updated when I print in this code, but the screen is not redrawn and I get the error as shown in the title. It is a dirty code, but I would like to know how to solve it.
This is my code:
class PlayPage extends StatefulWidget {
List gameList;
Map questionMap;
String category;
int myScore;
PlayPage({
required this.gameList,
required this.category,
required this.myScore,
required this.questionMap,
});
#override
State<PlayPage> createState() => _PlayPageState();
}
class _PlayPageState extends State<PlayPage> {
int quizNumber = 0;
int listNumber = 0;
var db = FirebaseFirestore.instance;
void changeQuiz() {
super.didChangeDependencies();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Stack(
children: [
Card(
child: SizedBox(
height: double.infinity,
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.only(
top: 20, bottom: 200, left: 20, right: 20),
child: Text(
widget.questionMap[widget.gameList[listNumber]][quizNumber],
style: const TextStyle(fontSize: 20),
),
),
),
),
),
Positioned(
right: 10,
bottom: 30,
child: Column(
children: [
ElevatedButton(
child: const Text(
"Pass",
style: TextStyle(fontSize: 30),
),
onPressed: () {
listNumber += 1;
quizNumber = 0;
setState(
() {
var docRef = db
.collection(widget.category)
.doc(widget.gameList[listNumber]);
docRef.get().then(
(DocumentSnapshot doc) {
var data = doc.data() as Map<String, dynamic>;
List questions = selectQuiz(
data["text"],
);
widget.questionMap = {
widget.gameList[listNumber]: questions
};
print(widget.questionMap);
},
);
},
);
},
),
const SizedBox(height: 30),
SizedBox(
width: 70,
height: 70,
child: FloatingActionButton(
backgroundColor:
(quizNumber < 9) ? Colors.teal : Colors.grey,
child: const Icon(
Icons.arrow_forward,
size: 35,
),
onPressed: () {
if (quizNumber < 9) {
setState(
() {
quizNumber += 1;
},
);
}
},
),
),
],
),
)
],
),
);
}
}
Make sure that the object you are trying to access is not null before you try to access it.
The error message NoSuchMethodError: The method '[]' was called on null is telling you that you've called the index ([]) operator on null.
This error occurs when a method or property has been called but it does not exist in the current context due to some type mismatch or incorrect data format being passed into it as an argument. Examine the stack trace and look at the line number where the failure occurred.
As mentioned here
For example, let's imagine you see:
Unhandled exception:
NoSuchMethodError: The method '[]' was called on null.
Receiver: null
Tried calling: []("data")
#0 Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:50:5)
#1 main (file:///Users/cbracken/foo.dart:3:23)
...
The stack trace above is telling you that the call on the null object
was in main on line 3 of file foo.dart. Further, it's telling you
that the [] operator was called with the parameter 'data'. If I
look at that line in my code and it says var foo = json['localteam']['data'], then I would deduce that
json['localteam'] is returning null.
It can be solved by identifying the exact location where it occurred followed by fixing typos/mistakes related argument passing along with ensuring proper variable declarations.
Related
While working on a flutter app to implement the pie chart from fl_chart package, I got the following error when I tried to run the program:
the getter 'touchinput' isn't defined for the type 'FlTouchEvent'. Try importing the library that defines 'touchInput', correcting the name to the name of an existing getter, or defining a getter or field named 'touchInput' <
Code Snippet of implementation
class _ActivityPieChartState extends State<ActivityPieChart> {
int _touchIndex = 0;
#override
Widget build(BuildContext context) {
return Container(
height: SizeConfig.blockSizeHorizontal * 25,
child: Card(
color: Colors.black,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(18)),
child: Row(
children: [
Container(
width: SizeConfig.blockSizeHorizontal * 60,
child: PieChart(
PieChartData(
borderData: FlBorderData(show: false),
//This is to make chart interactive when user touches areas of the chart
pieTouchData: PieTouchData(
touchCallback: (pieTouchResponse) {
setState(() {
if (pieTouchResponse.touchedSection is FlLongPressEnd ||
pieTouchResponse.touchedSection is FlPanEndEvent) {
_touchIndex = -1;
} else {
_touchIndex = pieTouchResponse.touchedSectionIndex;
}
});
},
),
),
),
)
],
),
),
);
}
}
how would I be able to fix this error?
Here toughCallback function takes two arguments (FlTouchEvent,PieTouchResponse) since you are not using FltouchEvent you can give underscore as your first argument (_).
I'm trying to add Applovin Interstitial ads to flutter app. But it keep showing errors. my sdk is sdk:'>=2.12.0 <3.0.0'.
This are the errors displayed
A value of type 'bool?' can't be assigned to a variable of type 'bool'.
Try changing the type of the variable, or casting the right-hand type to 'bool'.
The argument type 'dynamic Function(AppLovinAdListener)' can't be assigned to the parameter type 'dynamic Function(AppLovinAdListener?)'.
This is the sample code:
const CollectionCard();
#override
State<CollectionCard> createState() => _CollectionCardState();
}
class _CollectionCardState extends State<CollectionCard> {
AppLovinListener? get listener => null;
void initState() {
FlutterApplovinMax.initInterstitialAd('91b26a7777e1b455');
super.initState();
}
bool isInterstitialVideoAvailable = false;
#override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
/*24 is for notifications bar on Android */
final double itemHeight = (size.height - kToolbarHeight - 28) / 2;
final double itemWidth = size.width / 4;
return Container(
child: Padding(
padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 10.0),
child: Column(
children: <Widget>[
GridView.count(
primary: true,
padding: const EdgeInsets.fromLTRB(20, 0, 20, 20),
crossAxisSpacing: 10, //Reduce Horizontal Spacing
mainAxisSpacing: 10, //Reduce Vertical Spacing
crossAxisCount: 3,
physics: ScrollPhysics(),
childAspectRatio: (6 / 8),
// (itemWidth / itemHeight),
shrinkWrap: true,
children: <Widget>[
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
elevation: 2,
color: Theme.of(context).scaffoldBackgroundColor,
child: InkWell(
onTap: () async {
isInterstitialVideoAvailable =
await FlutterApplovinMax.isInterstitialLoaded (listener);
if (isInterstitialVideoAvailable) {
FlutterApplovinMax.showInterstitialVideo(
(AppLovinAdListener event) => listener (event));
}
Navigator.push(
context,
MaterialPageRoute(
builder: (ctx) => LearnPage(),
),
);
},
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ImageIcon(
AssetImage('assets/icons/learn.png'),
color: kLightPrimary,
size: 60,
), // Icon(
// layout.icon,
// size: 40,
// ),
Text(
'Learn',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
],
),
),
),
),
Below is an image of the code error
bool is a strict boolean - it can be true or false, nothing else.
bool? is a loose boolean or also called nullable - it can be true, false or null. Same goes for the function. The Plugin 'AppLovin' I assume you are using or the package, or the function you declared, doesn't support null-safety, which means that it's functions can return null. In order to solve the issue, you need to make the types nullable by adding a question mark after the type declaration (i.e. bool a; will become - bool? a; and make sure you don't call a method on a null. Since your variables and methods can return null, the editor will inform you before hand that this (the variable) might be null and calling a method on it will throw a MethodNotFoundException. Therefore, you should add your own logic to assure that this doesn't happen and satisfy the compiler by adding null-checks (exclamation marks - '!') to method calls which works as a form of asserting the compiler that this value isn't null, despite it being nullable. If it so happens that you do call a null on a value with a null check, at run time (after you press the run and load your page) you will get the following exception - Null-check used on a null value.
let's say I have a controller like this:
class ProfileController extends GetxController {
Rx<UserFacebookInfo?> facebookInfo = null.obs;
void facebookSync() async {
//
// logic to get user info from facebook
//
facebookInfo.value = UserFacebookInfo.fromFacebookApi(userData);
// facebookInfo = UserFacebookInfo.fromFacebookApi(userData).obs; <=== also tried this
update();
}
}
}
and in widget I have something like this:
Widget buildFacebook() => Padding(
padding: const EdgeInsets.only(top: 30.0, right: 20.0, left: 20.0, bottom: 10.0),
child: Obx(() => (_profileController.facebookInfo.value == null) ? Column(
children: [
IconButton(
icon : const Icon(Icons.facebook_outlined, size: 40.0),
onPressed: () => _profileController.facebookSync()
),
const Text(
'Facebook',
style: TextStyle(color: Colors.white),
)
],
) :
Column(
children: [
UserProfileAvatar(
avatarUrl: _profileController.facebookInfo.value!.facebookAvatar,
radius: 40,
),
Text(
_profileController.facebookInfo.value!.name,
style: const TextStyle(color: Colors.white),
)
],
)
));
and because initial value nullable, it's not working and not changing widget on a fly, but only if I update it from android studio. What is the correct way to initialize it??? I had similar case with nullable string observable so I was able to initialize it lie String string (null as String?).obs` Thanks for any advice
You can initialize nullable observables by using Rxn<Type>().
Therefore use this:
final facebookInfo= Rxn<UserFacebookInfo>();
This error just been a while before the data passed successfully from loading screen.
The loading screen that passing data :
if i print the instance on here, the error is not appeared
void setupWorldTime() async {
WorldTime instance = WorldTime(location: 'Jawa Timur', flag: 'jakarta.png', url: 'Asia/Jakarta');
await instance.getTime();
Navigator.pushReplacementNamed(context, '/home', arguments: {
'location': instance.location,
'flag': instance.flag,
'time': instance.time,
});
}
The home screen which is receiving data :
Map data = {};
#override
Widget build(BuildContext context) {
data = ModalRoute.of(context)!.settings.arguments as Map;
print(data['location']);
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.only(top: 50),
child: Column(
children: [
TextButton.icon(
onPressed: () {
Navigator.pushNamed(context, '/location');
},
icon: const Icon(Icons.edit_location),
label: const Text('Edit Location'),
),
const SizedBox(
height: 20,
),
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Text(
data['time'],
style: const TextStyle(
fontSize: 30,
),
),
]),
],
),
),
),
);
}
print(data['location']); printing the data perfectly, but before it the error above showing instantly, is that mean the print method expected the value of data is null before it is receive the value? how to fix it
Your method setupWorldTime is an async function and will not call the Navigator.pushReplacementNamed bit until instance.getTime() has returned. Because your home screen starts without its arguments set, data = ModalRoute.of(context)!.settings.arguments as Map will set data to null, leading to your error. Only once instance.getTime() has returned will build() be called again, this time with data != null and your message disappears.
To fix this, in your build function you should test for data == null and show something else (like a loading indicator) if data is indeed still null, or use a FutureBuilder (preferred).
This is the code
import 'package:flutter/material.dart';
import 'Authentication.dart';
import 'photoUpload.dart';
import 'Posts.dart';
import 'package:firebase_database/firebase_database.dart';
// import 'package:flutter_blogapp/Authentication.dart';
// import 'package:flutter_blogapp/photoUpload.dart';
class HomePage extends StatefulWidget
{
HomePage
(
{
this.auth,
this.onSignedOut,
}
);
final AuthImplementation auth;
final VoidCallback onSignedOut;
#override
State<StatefulWidget> createState()
{
return _HomePageState();
}
}
class _HomePageState extends State<HomePage>
{
List<Posts> postsList = [];
#override
void initState()
{
super.initState();
DatabaseReference postsRef = FirebaseDatabase.instance.reference().child("Posts");
postsRef.once().then((DataSnapshot snap)
{
var KEYS = snap.value.keys;
var DATA = snap.value;
postsList.clear();
for(var individualKey in KEYS)
{
Posts posts = new Posts
(
DATA[individualKey]['image'],
DATA[individualKey]['desctiption'],
DATA[individualKey]['data'],
DATA[individualKey]['time'],
);
postsList.add(posts);
}
setState(()
{
print('Length : $postsList.length');
});
});
}
void _logoutUser() async
{
try
{
await widget.auth.signOut();
widget.onSignedOut();
}
catch (e)
{
print(e.toString());
}
}
#override
Widget build(BuildContext context)
{
return new Scaffold
(
appBar: new AppBar
(
title: new Text('Home'),
),
body : new Container
(
child: postsList.length == 0 ? new Text(" No Post available ") : new ListView.builder
(
itemCount: postsList.length,
itemBuilder: (_, index)
//itemBuilder: (BuildContext _, int index ) //<-----
{
return PostsUI(postsList[index].image, postsList[index].description, postsList[index].date, postsList[index].time);
}
),
),
bottomNavigationBar: new BottomAppBar
(
color: Colors.pink,
child: new Container
(
margin: const EdgeInsets.only(left: 70.0, right: 70.0),
child: new Row
(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: <Widget>
[
new IconButton
(
icon: new Icon(Icons.local_car_wash),
iconSize: 50,
color: Colors.white,
onPressed: _logoutUser,
),
new IconButton
(
icon: new Icon(Icons.add_a_photo),
iconSize: 50,
color: Colors.white,
onPressed: ()
{
Navigator.push
(
context,
MaterialPageRoute(builder: (context)
{
return new UploadPhotoPage();
})
);
},
),
],
),
),
),
);
}
// Designing Posts UI <remove from Text field><??'defaut value'>
Widget PostsUI(String image, String description, String date, String time)
{
return new Card
(
elevation: 10.0,
margin: EdgeInsets.all(15.0),
child: new Container
(
padding: new EdgeInsets.all(14.0),
child: new Column
(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>
[
new Row
(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>
[
new Text
(
date,
style: Theme.of(context).textTheme.subtitle,
textAlign: TextAlign.center,
),
new Text
(
time,
style: Theme.of(context).textTheme.subtitle,
textAlign: TextAlign.center,
), //<----
],
),
SizedBox(height: 10.0,),
new Image.network(image, fit:BoxFit.cover),
SizedBox(height: 10.0,),
new Text
(
description, //= null ? "true" : "False", //??'defaut value'
style: Theme.of(context).textTheme.subhead,
textAlign: TextAlign.center,
),
],
)
)
);
}
}
The error that i was getting
The following assertion was thrown building: A non-null String must be
provided to a Text widget. 'package:flutter/src/widgets/text.dart':
Failed assertion: line 285 pos 10: 'data != null'
Either the assertion indicates an error in the framework itself, or we
should provide substantially more information in this error message to
help you determine and fix the underlying cause. In either case,
please report this assertion by filing a bug on GitHub:
https://github.com/flutter/flutter/issues/new?template=BUG.md
When the exception was thrown, this was the stack
2 new Text package:flutter/…/widgets/text.dart:285
3 _HomePageState.PostsUI package:flutter_blogapp/HomePage.dart:184
4 _HomePageState.build. package:flutter_blogapp/HomePage.dart:100
5 SliverChildBuilderDelegate.build package:flutter/…/widgets/sliver.dart:446
6 SliverMultiBoxAdaptorElement._build. package:flutter/…/widgets/sliver.dart:1260
What can i do to retrieve the data in my app? I have tried what i can do. can some one help me in finding where am I wrong? I have started learning recently.
First thing, pull the code out of the initState and put in a different function. This will keep your initState clean.
What I can see is you're trying to update data in firestore.
What you could do is define a new function as follows:
final databaseReference = Firestore.instance;
setPostsData() async {
DocumentSnapshot snapshot = await databaseReference
.collection("NAME_OF_COLLECTION")
.document("NAME_OF_DOCUMENT")
.get();
// use this DocumentSnapshot snapshot to get the current data that is there in the document inside of your collection.
var currentData = snapshot.data;
print(currentData); // to check whats actually there and if its working...
//lets assume newPostsList is the data that you want to put in this referenced document.
//to update the data in firestore:
await databaseReference
.collection("NAME_OF_COLLECTION")
.document("NAME_OF_DOCUMENT")
.updateData({newPostsList});
}
Then you can put setPostsData in the initState.
For this to work, you might want to redesign your database structure, for example: it should be like users --> posts --> List_of_all_posts. If did this way, NAME_OF_COLLECTION will be users and NAME_OF_DOCUMENT will be posts.