유지 참고 사항
AutomaticKeepAliveClientMixin
를 사용하면 간단히 해결할 수 있습니다.이미지 유지 예제 클래스입니다.
class ImageKeepAliveWidget extends StatefulWidget {
const ImageKeepAliveWidget({Key? key}) : super(key: key);
@override
State<ImageKeepAliveWidget> createState() => _ImageKeepAliveWidgetState();
}
/// use [AutomaticKeepAliveClientMixin] keeping the state
class _ImageKeepAliveWidgetState extends State<ImageKeepAliveWidget>
with AutomaticKeepAliveClientMixin<ImageKeepAliveWidget> {
String? _imageUrl;
@override
void initState() {
super.initState();
_fetchUrl();
}
void _fetchUrl() async {
try {
http.Response res =
await http.get(Uri.parse('https://dog.ceo/api/breeds/image/random'));
_imageUrl = json.decode(res.body)['message'];
setState(() {});
} catch (e) {
debugPrint('error in getting image url');
}
}
@override
Widget build(BuildContext context) {
/// must add super.build(context) to preserve state
super.build(context);
if (_imageUrl?.isNotEmpty == true) {
return Image.network(_imageUrl!);
} else {
return const CircularProgressIndicator();
}
}
@override
bool get wantKeepAlive => true;
}
그러나 메커니즘은 어떻게 작동합니까? 먼저 ListView를 살펴보겠습니다.
ListView
addAutomaticKeepAlives
를 추적하면 ListView 자식 대리자가 사용 중SliverChildListDelegate
을 찾을 수 있습니다. 빌드 기능 내에서 addAutomaticKeepAlives
가 true인지 확인할 수 있으며 하위 위젯은 AutomaticKeepAlive
위젯으로 래핑됩니다.@override
Widget? build(BuildContext context, int index) {
/// ...
if (addAutomaticKeepAlives)
child = AutomaticKeepAlive(child: child);
return KeyedSubtree(key: key, child: child);
}
AutomaticKeepAlive
는 무엇을 할까요?_AutomaticKeepAliveState
를 확인하면 이 stateful 위젯이 업데이트될 때 _updateChild
가 호출되는 것을 볼 수 있습니다. KeepAliveNotification을 수신하기 위해 NotificationListener를 래핑합니다. 그리고 나중에 수신기 위젯에 대한 KeepAlive
위젯을 래핑합니다.@override
void initState() {
super.initState();
_updateChild();
}
@override
void didUpdateWidget(AutomaticKeepAlive oldWidget) {
super.didUpdateWidget(oldWidget);
_updateChild();
}
void _updateChild() {
_child = NotificationListener<KeepAliveNotification>(
onNotification: _addClient,
child: widget.child!,
);
}
@override
Widget build(BuildContext context) {
assert(_child != null);
return KeepAlive(
keepAlive: _keepingAlive,
child: _child!,
);
}
알림 콜백이 리스너 위젯에서 무엇을 했는지 확인해 봅시다.
요컨대 콜백 함수에는 두 가지 주요 목표가 있습니다. 하나는 맵을 사용하여 KeepAliveNotification 핸들러를 저장하는 것입니다. 다른 하나는 나중에
KeepAlive
위젯인 자식에 부모 데이터를 적용하는 것입니다.bool _addClient(KeepAliveNotification notification) {
final Listenable handle = notification.handle;
_handles ??= <Listenable, VoidCallback>{};
assert(!_handles!.containsKey(handle));
_handles![handle] = _createCallback(handle);
handle.addListener(_handles![handle]!);
if (!_keepingAlive) {
_keepingAlive = true;
final ParentDataElement<KeepAliveParentDataMixin>? childElement = _getChildElement();
if (childElement != null) {
// If the child already exists, update it synchronously.
_updateParentDataOfChild(childElement);
} else {
// If the child doesn't exist yet, we got called during the very first
// build of this subtree. Wait until the end of the frame to update
// the child when the child is guaranteed to be present.
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
if (!mounted) {
return;
}
final ParentDataElement<KeepAliveParentDataMixin>? childElement = _getChildElement();
assert(childElement != null);
_updateParentDataOfChild(childElement!);
});
}
}
return false;
}
ParentDataElement<KeepAliveParentDataMixin>? _getChildElement() {
///...
}
KeepAlive
위젯에서 부모 데이터가 applyParentData
의 알림으로 renderObject keepAlive 상태를 설정하는 방법에 대한 AutomaticKeepAliveClientMixin
함수를 볼 수 있습니다. keepAlive가 아니면 renderObject가 레이아웃을 다시 실행합니다.@override
void applyParentData(RenderObject renderObject) {
assert(renderObject.parentData is KeepAliveParentDataMixin);
final KeepAliveParentDataMixin parentData = renderObject.parentData! as KeepAliveParentDataMixin;
if (parentData.keepAlive != keepAlive) {
parentData.keepAlive = keepAlive;
final AbstractNode? targetParent = renderObject.parent;
if (targetParent is RenderObject && !keepAlive)
targetParent.markNeedsLayout(); // No need to redo layout if it became true.
}
}
요약하면 전체 프로세스는 다음과 같습니다.
Reference
이 문제에 관하여(유지 참고 사항), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/maylau/note-to-keep-alive-p8m텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)