异步函数setState()导致内存泄漏的错误

最近使用 Flutter 做项目的时候需要用到网络请求,这是几乎所有市面上的 APP 都具有的功能。由于网络请求是一种耗时操作,需要开启线程,在 Flutter 中就是开启一个单独的 isolate 异步完成网络请求的功能,请求结束后使用 setState() 方法重新渲染界面,这应该是一种很常规的方法,但在使用 setState() 后却报了内存泄漏的错误。

打印的错误如下:

E/flutter (19573): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: setState() called after dispose(): WeatherDataPageState#21758(lifecycle state: defunct, not mounted)
E/flutter (19573): 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 (19573): 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 (19573): 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().

当然我们可以根据错误的提示解决这个问题,在错误的第一行和第三行已经告诉了我们造成错误的原因,原因如下:

lifecycle state: defunct, not mounted
Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.

经过查找,发现 mounted 是 Flutter framework 层的一个 get 方法,并且可以通过源码找到错误的线索,如下:

/// It is an error to call [setState] unless [mounted] is true.
bool get mounted => _element != null;

通过注释可以知道,除非[mounted]为真,否则调用[setState]是错误的。

所以改进了方案,在使用 setState() 方法之前,先判断一下 mounted 是否为真,代码入下:

if (mounted) {
	setState((){
		//...
	});
}

这样就解决了异步函数setState()导致内存泄漏的错误。

你可能感兴趣的:(Flutter基础)