본문 바로가기
expert

원치 않는 위젯 빌드를 처리하는 방법은 무엇입니까?

by RWriter 2023. 1. 24.
반응형

질문 제목:

원치 않는 위젯 빌드를 처리하는 방법은 무엇입니까?

질문 내용:

여러 가지 이유로

build

내 위젯의 메서드가 다시 호출되는 경우가 있습니다.부모가 업데이트했기 때문에 발생한다는 것을 알고 있습니다. 그러나 이것은 바람직하지 않은 결과를 초래합니다. 문제를 일으키는 일반적인 상황은

FutureBuilder

다음과 같은 방법을 사용할 때입니다.

@override
Widget build(BuildContext context) {
  return FutureBuilder(
    future: httpCall(),
    builder: (context, snapshot) {
      // create some layout here
    },
  );
}

이 예제에서

빌드

메서드를 다시 호출하면 다른 HTTP 요청이 트리거됩니다. 바람직하지 않습니다.이를 고려할 때 원치 않는 빌드를 처리하는 방법은 무엇입니까? 빌드 호출을 방지하는 방법이 있습니까?

해결 답변:

 

빌드

방법 은

부작용 없이 순수

해야 하는 방식으로 설계되었습니다 . 이는 다음과 같은 많은 외부 요인이 새 위젯 빌드를 트리거할 수 있기 때문입니다.

  • 루트 팝/푸시
  • 일반적으로 키보드 모양 또는 방향 변경으로 인한 화면 크기 조정
  • 부모 위젯이 자식을 다시 만들었습니다.
  • Class.of(context)위젯이 ( 패턴) 변경 에 의존하는 InheritedWidget

이는 build메서드가 http 호출을 트리거하거나 상태를 수정하지 않아야

함을 의미합니다 .


이것이 질문과 어떤 관련이 있습니까?

직면한 문제는 빌드 방법에 부작용이 있거나 순수하지 않아 외부 빌드 호출이 번거롭다는 것입니다.빌드 호출을 방지하는 대신 빌드 메서드를 순수하게 만들어 영향 없이 언제든지 호출할 수 있도록 해야 합니다.예제의 경우 위젯을 로 변환한

StatefulWidget

다음 해당 HTTP 호출을 로 추출

initState

합니다

State

.

class Example extends StatefulWidget {
  @override
  _ExampleState createState() => _ExampleState();
}

class _ExampleState extends State<Example> {
  Future<int> future;

  @override
  void initState() {
    future = Future.value(42);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: future,
      builder: (context, snapshot) {
        // create some layout here
      },
    );
  }
}

나는 이것을 이미 알고 있다. 나는 재건축을 최적화하고 싶어서

여기 에 왔습니다.

자식도 강제로 빌드하지 않고 다시 빌드할 수 있는 위젯을 만드는 것도 가능합니다.위젯의 인스턴스가 동일하게 유지되는 경우 Flutter는 의도적으로 자식을 다시 빌드하지 않습니다. 이는 불필요한 재구축을 방지하기 위해 위젯 트리의 일부를 캐시할 수 있음을 의미합니다.가장 쉬운 방법은 다트

const

생성자를 사용하는 것입니다.

@override
Widget build(BuildContext context) {
  return const DecoratedBox(
    decoration: BoxDecoration(),
    child: Text("Hello World"),
  );
}

 

const

해당 키워드 덕분에

DecoratedBox

빌드가 수백 번 호출되더라도 인스턴스의 인스턴스는 동일하게 유지됩니다.그러나 동일한 결과를 수동으로 얻을 수 있습니다.

@override
Widget build(BuildContext context) {
  final subtree = MyWidget(
    child: Text("Hello World")
  );

  return StreamBuilder<String>(
    stream: stream,
    initialData: "Foo",
    builder: (context, snapshot) {
      return Column(
        children: <Widget>[
          Text(snapshot.data),
          subtree,
        ],
      );
    },
  );
}

이 예에서 StreamBuilder에 새 값이 통보

subtree

되면 StreamBuilder/Column이 다시 작성하더라도 다시 작성되지 않습니다. 클로저 덕분에 인스턴스가

MyWidget

변경되지 않았기 때문에 발생합니다.이 패턴은 애니메이션에서 많이 사용됩니다. 일반적인 용도는

AnimatedBuilder

및 와 같은 모든 전환

AlignTransition

입니다.클래스의 필드에 저장할 수도

subtree

있지만 핫 리로드 기능을 중단하므로 덜 권장됩니다.

반응형

댓글