I'm trying to create nfc emulator in flutter app using the dart package (https://pub.dev/packages/nfc_emulator)
I have added emulator services to AndroidManifest.xml file and then started getting build error.
This is the emulator service tag of AndroidManifest.xml.
<service
android:name="io.flutter.plugins.nfc_emulator.NfcEmulatorService"
android:exported="true"
android:permission="android.permission.BIND_NFC_SERVICE">
<!-- Intent filter indicating that we support card emulation. -->
<intent-filter>
<action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<!--
Required XML configuration file, listing the AIDs that we are emulating cards
for. This defines what protocols our card emulation service supports.
-->
<meta-data
android:name="android.nfc.cardemulation.host_apdu_service"
android:resource="#xml/aid_list" />
</service>
This is my dart code:
class NFC extends StatefulWidget {
#override
State<NFC> createState() => _NFCState();
}
class _NFCState extends State<NFC> {
// BottomSheetWidget({super.key});
TextEditingController controller = TextEditingController();
TextEditingController ctrl = TextEditingController();
String _platformVersion = 'Unknown';
NfcStatus _nfcStatus = NfcStatus.unknown;
bool _started = false;
#override
void initState() {
super.initState();
initPlatformState();
}
Future<void> initPlatformState() async {
String? platformVersion;
NfcStatus nfcStatus = NfcStatus.unknown;
try {
platformVersion = await NfcEmulator.platformVersion;
nfcStatus = await NfcEmulator.nfcStatus;
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
if (!mounted) return;
setState(() {
_platformVersion = platformVersion ?? 'Unknown';
_nfcStatus = nfcStatus;
});
}
#override
Widget build(BuildContext context) {
return Container(
height: 800,
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
// mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 8),
child: Text('Add details'),
),
TextField(controller: controller, hint: 'cardAid'),
TextField(
controller: ctrl,
hint: 'cardUid',
),
TextButton(
onPressed: () {
startStopEmulator();
},
child: Text('Submit'))
],
),
),
);
}
void startStopEmulator() async {
if (_started) {
await NfcEmulator.stopNfcEmulator();
} else {
await NfcEmulator.startNfcEmulator(
controller.text,
ctrl.text,
);
//}
}
}
This is the build error that I'm getting.
Exception: Gradle task assembleDebug failed with exit code 1
I started getting error on adding the emulator services.
Related
I am using a package permission handler in my app. I am using an android 9 mobile.
This is my AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.light_chat">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="28"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
android:maxSdkVersion="28"/>
<uses-permission android:name="android.permission.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION"/>
<application
android:requestLegacyExternalStorage="true">
android:label="light_chat"
android:name="${applicationName}"
android:icon="#mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="#style/LaunchTheme"
android:configChanges=
"orientation|keyboardHidden|keyboard|screenSize|
smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="#style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
android:usesCleartextTraffic="true"
</application>
</manifest>
And This is my homePage where I am making the permission function
and calling in initState();
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:light_chat/layout/const_size.dart';
import 'package:light_chat/layout/repeateCode.dart';
import 'package:permission_handler/permission_handler.dart';
import 'sign_in.dart';
import 'functions.dart';
import 'chat_room.dart';
import 'package:permission_handler/permission_handler.dart';
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
late final size = MediaQuery
.of(context)
.size;
bool isLoading = false;
Map<String, dynamic>? userMap;
TextEditingController _serachBarController = TextEditingController();
FirebaseAuth _auth = FirebaseAuth.instance;
String chatRoomId(String user1, String user2){
if(user1[0].toLowerCase().codeUnits[0] >
user2[0].toLowerCase().codeUnits[0]){
return '$user1 $user2';
}
else
{
return '$user2 $user1';
}
}
#override
void onSearch() async {
FirebaseFirestore _firestore = FirebaseFirestore.instance;
setState(() {
isLoading = true;
});
await _firestore.collection('users').where(
'email', isEqualTo: _serachBarController.text)
.get().then((value) {
setState(() {
if (value.docs.length > 0) {
userMap = value.docs[0].data();
print(userMap);
isLoading = false;
}
});
});
}
FirebaseFirestore _firestore = FirebaseFirestore.instance;
#override
void initState() {
permission();
WidgetsBinding.instance.addObserver(this);
statusChange('Online');
// TODO: implement initState
super.initState();
}
Here is the permission function i want to allow my mobile second permission
var status1
but my stack thorwing exception that is no permission in menifest file.
i am using android 9 so this is the problem
those permissions i am adding in menifest, for android 11.
i want to know which permission i add in menifest for android 9 or under 9.
void permission ()async{
// var status0= await Permission.storage.status;
// if (!status0.isGranted){
// await Permission.storage.request();
// }
var status1= await Permission.manageExternalStorage.status;
if (!status1.isGranted){
await Permission.manageExternalStorage.request();
}
}
void statusChange(String status)async{
await _firestore.collection('users').doc(_auth.currentUser!.uid).update(
{
'status' : status
});
}
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
if(state == AppLifecycleState.resumed){
statusChange('Online');
}
else
{
statusChange('Offline');
}
// TODO: implement didChangeAppLifecycleState
super.didChangeAppLifecycleState(state);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Home',),
actions: [
IconButton(onPressed: () => logOut(context), icon: Icon(Icons.logout))
],
backgroundColor: Colors.blue,),
body: isLoading ?
Center(child:
Container(
height: size.height / 20,
width: size.width / 20,
child: CircularProgressIndicator(),
),)
: Column(
children: [
SizedBox(height: 10.0,),
RepeateTextFieldCode(controller: _serachBarController,
keyboardType: TextInputType.emailAddress,
lableText: 'Search'),
ElevatedButton(onPressed: () => onSearch(),
child: Text('Search', style: buttonText,),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.blue),
),
),
userMap != null ?
ListTile(
onTap: () {
String roomId = chatRoomId(_auth.currentUser!.displayName!,
userMap?['name']);
Navigator.push(context,MaterialPageRoute(builder: (_)=> ChatRoom(
chatRoomId: roomId,
userMap: userMap,
)));
},
title: Text(userMap?['name'], style: titleText,),
subtitle: Text(userMap?['email'], style: subtitleText,),
leading: Icon(Icons.account_box, color: Colors.black,),
trailing: Icon(Icons.chat, color: Colors.black,),
) :
Container(),
],
),
);
}
}
i need to make an audio listening application and in that need to implement a seeker. Now i can listen to audio and also able to pause it but when i seeks the audio.It starts again.
I used Audioplayers(https://pub.dev/packages/audioplayers) package version : ^0.20.1 for that.
import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
class PlayAudio extends StatefulWidget {
const PlayAudio({Key? key}) : super(key: key);
#override
State<PlayAudio> createState() => _PlayAudioState();
}
class _PlayAudioState extends State<PlayAudio> {
var value=0.0;
bool isPlaying=false;
Duration duration=const Duration();
Duration position=const Duration();
AudioPlayer audioPlayer=AudioPlayer();
// AudioPlayer player = AudioPlayer();
#override
void initState() {
// TODO: implement initState
super.initState();
audioPlayer.onPlayerStateChanged.listen((event) {
setState((){
isPlaying=event==PlayerState.PLAYING;
});
});
///listen to audio duration
audioPlayer.onDurationChanged.listen((event) {
setState((){
duration=event;
});
});
audioPlayer.onAudioPositionChanged.listen((event) {
setState((){
position=event;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
InkWell(
onTap: ()async{
if(isPlaying){
await audioPlayer.pause();
}else if(!isPlaying){
String url="https://www.learningcontainer.com/wp-content/uploads/2020/02/Kalimba.mp3";
await audioPlayer.play(url);
}
},
child: Container(
color: Colors.red,
child: const Padding(
padding: EdgeInsets.all(8.0),
child: Text("play Audio"),
),
),
),
Slider.adaptive(
min: 0.0,
value: position.inSeconds.toDouble(),
max: 120,
onChanged: (value1)async{
Duration newDuration = Duration(seconds: value1.toInt());
await audioPlayer.seek(newDuration);
}),
Text(formatTime(position)),
Text(formatTime(duration-position)),
],
),
),
);
}
String formatTime(Duration duration){
String twoDigits(int n)=>n.toString().padLeft(2,"0");
final hours=twoDigits(duration.inHours);
final minutes=twoDigits(duration.inMinutes.remainder(60));
final seconds=twoDigits(duration.inSeconds.remainder(60));
return [
if(duration.inHours>0) hours,minutes,seconds
].join(":");
}
}
when i checked it on IOS simulator it working fine but in android real device it showing the problem.
I have this error when using flutter_barcode_scanner :
Local module descriptor class for com.google.android.gms.vision.barcode not found.
Error loading optional module com.google.android.gms.vision.barcode: com.google.android.gms.dynamite.DynamiteModule$LoadingException: No acceptable module found. Local version is 0 and remote version is 0.
Local module descriptor class for com.google.android.gms.vision.dynamite.barcode not found.
D/ViewRootImpl#9677bb1BarcodeCaptureActivity: ViewPostIme pointer 0
could any one help me please!
how to reproduce :
1- I just run the example provided with package
2- select scan barcode
3- the app ask for permission -> accept giving the permission
4- the scanner keep scan and did not catch the barcode
5- the error appear in android studio in the run tab
main.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_barcode_scanner/flutter_barcode_scanner.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _scanBarcode = 'Unknown';
#override
void initState() {
super.initState();
}
Future<void> startBarcodeScanStream() async {
FlutterBarcodeScanner.getBarcodeStreamReceiver(
'#ff6666', 'Cancel', true, ScanMode.BARCODE)!
.listen((barcode) => print(barcode));
}
Future<void> scanQR() async {
String barcodeScanRes;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
barcodeScanRes = await FlutterBarcodeScanner.scanBarcode(
'#ff6666', 'Cancel', true, ScanMode.QR);
print(barcodeScanRes);
} on PlatformException {
barcodeScanRes = 'Failed to get platform version.';
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
_scanBarcode = barcodeScanRes;
});
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> scanBarcodeNormal() async {
String barcodeScanRes;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
barcodeScanRes = await FlutterBarcodeScanner.scanBarcode(
'#ff6666', 'Cancel', true, ScanMode.BARCODE);
print(barcodeScanRes);
} on PlatformException {
barcodeScanRes = 'Failed to get platform version.';
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
_scanBarcode = barcodeScanRes;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Barcode scan')),
body: Builder(builder: (BuildContext context) {
return Container(
alignment: Alignment.center,
child: Flex(
direction: Axis.vertical,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () => scanBarcodeNormal(),
child: Text('Start barcode scan')),
ElevatedButton(
onPressed: () => scanQR(),
child: Text('Start QR scan')),
ElevatedButton(
onPressed: () => startBarcodeScanStream(),
child: Text('Start barcode scan stream')),
Text('Scan result : $_scanBarcode\n',
style: TextStyle(fontSize: 20))
]));
})));
}
}
Please make sure you have added these permissions in your app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<application ...>
...
</application>
I faced the same problem
Try to run on another mobile
I am new to flutter and trying to create a geolocation.
however, for my following code, the screen only shows 'Loading.. Please wait..' and the map is not showing.
i am just trying to show the current location using dependencies
geolocator: ^6.1.1
Using the codes from
https://codelabs.developers.google.com/codelabs/google-maps-in-flutter#3
the Google map can be shown successfully. So it is not issues related to Google Maps Platform.
// home.dart
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
bool mapToggle = false;
var currentLocation;
GoogleMapController mapController;
#override
void initState() {
// TODO: implement initState
super.initState();
Geolocator.getCurrentPosition().then((currloc) {
setState(() {
currentLocation = currloc;
mapToggle = true;
});
});
}
void _onMapCreated(controller) {
setState(() {
mapController = controller;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: Column(children: <Widget>[
Stack(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height - 80.0,
width: double.infinity,
child: mapToggle
? GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: LatLng(currentLocation.latitude,
currentLocation.longitude),
zoom: 10.0))
: Center(
child: Text(
'Loading.. Please wait..',
style: TextStyle(fontSize: 20.0),
)))
],
)
]),
);
}
}
In your AndroidManifest add permission
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
initialize variable
Position _currentPosition;
Copy this function and call this in initState
_getCurrentLocation() async{
Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.best)
.then((Position position) {
setState(() {
_currentPosition = position;
});
}).catchError((e) {
print(e);
});
}
For more info checkout their pub.dev site geolocatorunder usage,make sure you setup correctly for android and ios
As #theredcap already pointed out in his comment, you most probably don't have the necessary permissions. Always read the documentation of the plugin that you are using.
I don't see:
LocationPermission permission = await Geolocator.checkPermission();
nor do I see:
LocationPermission permission = await Geolocator.requestPermission();
in your code at all, yet the plugin docs clearly explain that part. Also, in case you are new to Android in general, take a look at: https://developer.android.com/training/location/permissions
the error is thrown in two areas (and the app freezes (when the app is minimized, when phones back button is clicked, or when another app runs on top of the flutter app. Flutter version: 1.20.2 (previous versions did not have this issue): The two functions are:
#override
void initState() {
super.initState();
getItems();
}
getItems() async {
initClearVisibility();
initFilters();
setState(() {
loadingItems = true;
Visibility(visible: true, child: CircularProgressIndicator());
});
QuerySnapshot querySnapshot = await query.get();
items = querySnapshot.docs;
lastDocument = querySnapshot.docs[querySnapshot.docs.length - 1];
setState(() {
loadingItems = false;
Visibility(visible: false, child: CircularProgressIndicator());
});
}
initClearVisibility() {
if (Str.filterSelectCategory != Str.CATEGORY) {
clearCategoryVisible = true;
allCategoriesVisible = false;
categoryValue = Str.filterSelectCategory;
setState(() {});
}
}
initFilters() async {
filterDefaultItems();
}
filterDefaultItems() async {
query = _firestore
.collection(Str.ITEMS)
.where(Str.IS_ITEM_SOLD, isEqualTo: false)
.where(Str.ADDRESS, isEqualTo: userAddress1)
//.orderBy(Str.DATE_POSTED)
.limit(perPage);
}
Second area is on the following code where I am also getting: :
class FABBottomAppBarItem {
FABBottomAppBarItem({this.iconData, this.itemColor}); //, this.text});
IconData iconData;
var itemColor;
//String text;
}
class FABBottomAppBar extends StatefulWidget {
FABBottomAppBar({
this.items,
this.centerItemText,
this.height: 65.0,
this.iconSize: 24.0,
this.backgroundColor,
this.color,
this.selectedColor,
this.notchedShape,
this.onTabSelected,
}) {
assert(this.items.length == 2 || this.items.length == 4);
}
final List<FABBottomAppBarItem> items;
final String centerItemText;
final double height;
final double iconSize;
final Color backgroundColor;
final Color color;
final Color selectedColor;
final NotchedShape notchedShape;
final ValueChanged<int> onTabSelected;
#override
State<StatefulWidget> createState() => FABBottomAppBarState();
}
class FABBottomAppBarState extends State<FABBottomAppBar> {
//int _selectedIndex = 0;
int unreadCount = 0;
_updateIndex(int index) {
widget.onTabSelected(index);
setState(() {
//_selectedIndex = index;
});
}
#override
void initState() {
super.initState();
countDocuments();
}
#override
Widget build(BuildContext context) {
List<Widget> items = List.generate(widget.items.length, (int index) {
return _buildTabItem(
item: widget.items[index],
index: index,
onPressed: _updateIndex,
);
});
items.insert(items.length >> 1, _buildMiddleTabItem());
return BottomAppBar(
shape: widget.notchedShape,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: items,
),
color: widget.backgroundColor,
);
}
Widget _buildMiddleTabItem() {
return Expanded(
child: SizedBox(
height: MediaQuery.of(context).size.height * 0.075, //widget.height,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(
height: MediaQuery.of(context).size.height * 0.04,
),
Text(
widget.centerItemText ?? '',
style: TextStyle(
color: BwerereTheme.bwerereRed,
fontSize: 14.0,
fontWeight: FontWeight.w900),
),
],
),
),
);
}
Widget _buildTabItem({
FABBottomAppBarItem item,
int index,
ValueChanged<int> onPressed,
})
{
return Expanded(
child: SizedBox(
height: MediaQuery.of(context).size.height * 0.065,
child: Material(
type: MaterialType.transparency,
child: InkWell(
onTap: () => onPressed(index),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Stack(
children: <Widget>[
Icon(item.iconData,
color: item.itemColor,
size: IconTheme.of(context).size * 1.2),
index == 2 ? badge() : Container()
],
)
],
),
),
),
),
);
}
Widget badge() => unreadCount < 1
? Container()
: Container(
padding: EdgeInsets.all(4.0),
decoration: BoxDecoration(
color: BwerereTheme.bwerereRed, shape: BoxShape.circle),
child: Center(
child: RobotoFont(
text: "$unreadCount",
textSize: 12.0,
textColor: Colors.white,
fontWeight: FontWeight.w400),
));
void countDocuments() async {
final uid = await FetchUserData().getCurrentUserID();
QuerySnapshot _myDoc = await FirebaseFirestore.instance
.collection("userUnreadMessages")
.doc(uid)
.collection(Str.MESSAGE_COLLECTION)
.get();
List<DocumentSnapshot> _myDocCount = _myDoc.docs;
setState(() {
unreadCount = _myDocCount.length;
print('NOTIY LENGTH::: $unreadCount');
});
}
}
THE ERROR FROM FRAMEWORK.DART for FABBottomAppBarState.
The same error thrown on the getItems on HomePage()
Exception has occurred.
FlutterError (setState() called after dispose(): FABBottomAppBarState#250ac(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().)
Further investigation then shows that the app takes about 400MB of memory (Ram) for the phone which I find rather too high.
Help on figuring out the issue will really help. Thanks in advance.
Additional information:
Error occurs when running on android 7.0, flutter 1.20.2. See similar/related issue on https://github.com/flutter/flutter/issues/35900. Note that I upgraded to Flutter 1.20.2 adnd Downgrading to 1.7.5 will require a lot of changes I made after upgrading especially on Firestore (NOTE: https://firebase.flutter.dev/docs/migration which was recently updated).
After an await, your widget may not be mounted anymore. Doing setState gives you an exception at that time. This is actually a good thing, the code that follows should not be executing anyway, since you are somewhere else.
You have three options about the "setState() called after dispose()" exception:
Safely ignore it. The exception is saving your async function from continuing. You will see an exception in your logs that you can just ignore.
Place a if (!mounted) return; between each await and setState(). It may be a good habit to put it after each await. This also stops the async function and hides the exception, if you are allergic to it.
Replace your setState() calls with setStateIfMounted() and define it as:
void setStateIfMounted(f) {
if (mounted) setState(f);
}
However, if (mounted) setState() does not stop the async function, so this 3rd option is the worst between the three as discussed here.
I also explain these approaches in this video.
You can use:
if (this.mounted) { // check whether the state object is in tree
setState(() {
// make changes here
});
}
The mounted checks whether Whether this State object is currently in a tree.
mounted class
For beginners and easy to understand check bool isMount = true; when dispose() would be called bool isMount = false; and setState() won't be called.
class TotalBooks extends StatefulWidget {
TotalBooks({Key? key}) : super(key: key);
// code omitted..
bool isMount = true;
#override
_TotalBooksState createState() => _TotalBooksState();
}
class _TotalBooksState extends State<TotalBooks> {
#override
void initState() {
// code omitted..
if (widget.isMount) {
setState(() {
// code omitted..
});
}
});
super.initState();
}
#override
void dispose() {
// TODO: implement dispose
widget.isMount = false;
// code omitted.. super.dispose();
}
#override
Widget build(BuildContext context) {
return SizedBox();
}
}
#override
void setState(VoidCallback fn) {
if (!mounted) return;
super.setState(fn);
}
I found there is no that perfect and easy way! I have written a subclass extends the State, you can use VMState instead of State, then just call safeSetState instead of setState.
import 'package:flutter/widgets.dart';
class VMState<T extends StatefulWidget> extends State<T> {
bool didDispose = false;
#override
Widget build(BuildContext context) {
// TODO: implement build
throw UnimplementedError();
}
#override
void dispose() {
didDispose = true;
super.dispose();
}
void safeSetState(VoidCallback callback) {
if (!didDispose) {
setState(callback);
}
}
}
Someone says to use mounted but that brings another exception.
With this code, my error has been solved!
if (mounted) {
setState(() {
// make your changes here
});
}