gpt4 book ai didi

flutter - Flutter-不再显示在小部件树中的小部件,或者此错误可能表示内存泄漏警告

转载 作者:行者123 更新时间:2023-12-03 03:14:31 24 4
gpt4 key购买 nike

我有3页,我用bottomNavigationBar检查过渡,第一页是Soclose,在此页中,我从数据库中获取信息并在屏幕上打印出来。
我正在从数据库中顺利获取信息,但是当我切换屏幕时,控制台会发出警告消息。控制台中出现错误,但应用程序正常运行。切换画面并返回到旧页面(关闭页面)时,出现错误页面并在几毫秒内消失。
我找不到类似的问题,并且尝试在警告中提出建议,但要么我做不到,要么解决方案不起作用。
enter image description here
enter image description here
相关的soclose dart文件:

class _Closesevents extends State<Soclose> {
List<Event> eventList;
int eventListLen;

@override
void initState() {
try{
final Future<Database> dbFuture = DbHelper.initializeDatabase();
dbFuture.then((database) {
Future<List<Event>> eventListFuture = DbHelper().getEventList();
eventListFuture.then((eventList) {
setState(() {
this.eventList = eventList;
this.eventListLen = eventList.length;
});
});
});}
catch (e,s)
{
print("[ERROR] $e");
print("[ERROR TREE]\n$s");
}
super.initState();
}

@override
void dispose() {
super.dispose();
}

@override
Widget build(BuildContext context) {
return Container(
child: new ListView.builder(
itemCount: eventListLen,
itemBuilder: (BuildContext context, int index) =>
buildTripCard(context, index)),
);
}

Widget buildTripCard(BuildContext context, int index)
...

Databasehelper文件
import ...

class DbHelper {
static DbHelper _databaseHelper; // Singleton DatabaseHelper
static Database _database;

static final String _tablename = EventConstants.TABLE_NAME;
static final String _columnId = EventConstants.COLUMN_ID;
static final String _columnTitle = EventConstants.COLUMN_TITLE;
static final String _columnDate = EventConstants.COLUMN_DATE;
static final String _columnStartTime = EventConstants.COLUMN_STARTTIME;
static final String _columnFinishTime = EventConstants.COLUMUN_FINISHTIME;
static final String _columnDesc = EventConstants.COLUMN_DESCRIPTION;
static final String _columnIsActive = EventConstants.COLUMN_ISACTIVE;

DbHelper._createInstance(); // Named constructor to create instance of DatabaseHelper

factory DbHelper() {

if (_databaseHelper == null) {
_databaseHelper = DbHelper._createInstance(); // This is executed only once, singleton object
}
return _databaseHelper;
}

Future<Database> get database async {

if (_database == null) {
_database = await initializeDatabase();
}
return _database;
}

static Future<Database> initializeDatabase() async {
Directory directory = await getApplicationDocumentsDirectory();
String path = directory.path + 'takvimapp.db';

// Open/create the database at a given path
var notesDatabase = await openDatabase(path, version: 1, onCreate: _createDb);
return notesDatabase;
}

static void _createDb(Database db, int newVersion) async {

await db.execute('CREATE TABLE $_tablename ( $_columnId INTEGER PRIMARY KEY NOT NULL,$_columnTitle TEXT ,$_columnDate TEXT,$_columnStartTime TEXT,$_columnFinishTime TEXT,$_columnDesc TEXT,$_columnIsActive INTEGER);');
}

// Get all events --map
Future<List<Map<String, dynamic>>> getEventMapList() async {
Database db = await this.database;
var result = await db.query(_tablename, orderBy: '$_columnTitle ASC');
return result;
}

// Insert Operation: Insert a Event object to database
Future<int> insertEvent(Event event) async {
Database db = await this.database;
var result = await db.insert(_tablename, event.toMap());
return result;
}

// Update Operation: Update a Event object and save it to database
Future<int> updateEvent(Event event) async {
var db = await this.database;
var result = await db.update(_tablename, event.toMap(), where: '$_columnId = ?', whereArgs: [event.id]);
return result;
}

// Delete Operation: Delete a Event object from database
Future<int> deleteEvent(int id) async {
var db = await this.database;
int result = await db.rawDelete('DELETE FROM $_tablename WHERE $_columnId = $id');
return result;
}

// Get number of Event objects in database
Future<int> getCount() async {
Database db = await this.database;
List<Map<String, dynamic>> x = await db.rawQuery('SELECT COUNT (*) from $_tablename');
int result = Sqflite.firstIntValue(x);
return result;
}

// Convert map to list
Future<List<Event>> getEventList() async {

var eventMapList = await getEventMapList(); // Get 'Map List' from database
int count = eventMapList.length; // Count the number of map entries in db table

List<Event> eventList = List<Event>();
// For loop to create a 'Event List' from a 'Event List'
for (int i = 0; i < count; i++) {
eventList.add(Event.fromMap(eventMapList[i]));
}

return eventList;
}
static Future closeDb() => _database.close();
}

错误警告会无限循环不断地写入控制台。
为了摆脱警告,我需要关闭应用程序并重新启动模拟器。
警告信息:

E/flutter (30455): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: setState() >called after dispose(): _CountDownItemState#2bbc3(lifecycle state: defunct, not mounted)

E/flutter (30455): 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.E/flutter (30455): 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.

E/flutter (30455): 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().


解:
  @override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: _db.getEventList(),
builder: (context, snapshot) {
if (snapshot.data == null) {
return Container(
child: Text("Loading....."),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(snapshot.data[index].title),
);
});
}
}),
);
}

最佳答案

问题在于您的initState函数覆盖。最好在所有其他逻辑之前调用initStatesuper.initState的 super 。您的Future可能完成得太快,甚至在初始化状态之前调用setState。只需将super.initState();移动为覆盖中的第一条语句。例如

@override
void initState() {
super.initState();//Always call this first

try{
final Future<Database> dbFuture = DbHelper.initializeDatabase();
dbFuture.then((database) {
Future<List<Event>> eventListFuture = DbHelper().getEventList();
eventListFuture.then((eventList) {
setState(() {
this.eventList = eventList;
this.eventListLen = eventList.length;
});
});
});}
catch (e,s)
{
print("[ERROR] $e");
print("[ERROR TREE]\n$s");
}
}
编辑:但是,这仍然会导致错误,因为在挂载小部件之前仍可以调用 setState。这就是 FutureBuilder小部件存在的原因。在 Future方法中包装需要此 build数据的小部件,将 Future传递给 futureFutureBuilder参数,然后使用 AsyncSnapshot提供的 builder访问数据。查看有关 FutureBuilder 的更多信息。

关于flutter - Flutter-不再显示在小部件树中的小部件,或者此错误可能表示内存泄漏警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62863526/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com