[dart] Flutter에서 Stateful과 Stateless 위젯의 관계는 무엇입니까?

상태 저장 위젯은 수명 내에서 상태를 변경하는 모든 위젯으로 정의됩니다. 그러나 a 가 자신의 자식 중 하나로 a StatelessWidget를 갖는 것은 매우 일반적인 관행입니다 StatefulWidget. 자식 중 하나 StatelessWidget가 있으면 상태 저장이 되지 StatefulWidget않습니까?

나는의 코드의 일부로 문서를 살펴 보았지만 StatelessWidget어떻게 할 StatelessWidget수 있는지 Statefulwidget를 자식으로 가질 수 있고 여전히 남아 있는지 알 수 없었다 StatelessWidget.

Flutter에서 Stateful과 Stateless 위젯의 관계와 차이점은 무엇입니까?



답변

StatelessWidget은 결코 재 구축 자체 (하지만 외부 이벤트에서 수행 할 수 있습니다)에 의해. StatefulWidget는 할 수 있습니다. 그것이 황금률입니다.

그러나 모든 종류의 위젯은 언제든지 다시 칠할 수 있습니다 .

Stateless only는 모든 속성이 변경 불가능 하며 속성을 변경 하는 유일한 방법은 해당 위젯의 새 인스턴스를 만드는 것임을 의미합니다. 예를 들어 위젯 트리를 잠그지 않습니다.

그러나 자녀의 유형에 대해 신경 쓰지 마십시오. 그것은 당신에게 어떤 영향도 미치지 않습니다.


답변

StatefulWidget 대 StatelessWidget.

여기에 이미지 설명 입력

StatelessWidget- 변경 가능한 상태가 필요하지 않은 위젯입니다.

  • 상태 비 저장 위젯은 사용자 인터페이스를보다 구체적으로 설명하는 다른 위젯 집합을 구축하여 사용자 인터페이스의 일부를 설명하는 위젯입니다. 빌드 프로세스는 사용자 인터페이스의 설명이 완전히 구체화 될 때까지 반복적으로 계속됩니다 (예 : 구체적인 RenderObject를 설명하는 RenderObjectWidgets로 완전히 구성됨).

  • stateless당신이 설명하는 인터페이스를 사용자의 부분은 객체 자체와의 구성 정보 이외에 의존하지 않을 때 위젯 유용
    BuildContext 위젯이 팽창되는. 내부 클럭 구동 상태가 있거나 일부 시스템 상태에 따라 동적으로 변경 될 수있는 컴포지션의 경우를 사용하는 것이
    StatefulWidget좋습니다.

class GreenFrog extends StatelessWidget {
  const GreenFrog({ Key key }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(color: const Color(0xFF2DBD3A));
  }
}

StatefulWidget- 변경 가능한 상태를 가진 위젯.

  • 상태 저장 위젯은 설명하는 사용자 인터페이스의 일부가 동적으로 변경 될 수있는 경우에 유용합니다.

Flutter가를 만들 때 StatefulWidgetState 객체를 만듭니다. 이 객체는 해당 위젯의 모든 변경 가능 상태가 유지되는 곳입니다.

상태의 개념은 다음 두 가지로 정의됩니다.

1) 위젯에서 사용하는 데이터가 변경 될 수 있습니다.

2) 위젯이 빌드 될 때 데이터를 동 기적으로 읽을 수 없습니다. (모든 상태는 빌드 메서드가 호출 될 때까지 설정되어야합니다).

StatefulWidget 수명주기

수명주기에는 다음과 같은 단순화 된 단계가 있습니다.

  1. createState () -Flutter가 StatefulWidget을 빌드하라는 지시를 받으면 즉시 createState().
  • 트리의 지정된 위치에이 위젯의 ​​변경 가능 상태를 만듭니다.

  • 하위 클래스는 연결된 State 하위 클래스의 새로 생성 된 인스턴스를 반환하려면이 메서드를 재정의해야합니다.

@override
_MyState createState() => _MyState();
  1. mount == true- 모든 위젯에 bool this.mounted속성이 있습니다. buildContext가 할당 되면 참 이됩니다. setState위젯이 마운트 해제 될 때 호출하는 것은 오류 입니다. 이 State 개체가 현재 트리에 있는지 여부입니다.
  • State 객체를 생성 한 후를 호출하기 전에 initState프레임 워크는 State 객체를
    BuildContext. State 객체는 프레임 워크가를
    호출 할 때까지 마운트 된 상태로 유지되며 그 dispose()이후에는 프레임 워크가
    State 객체에 다시 빌드를 요청하지 않습니다 .

  • mount가 true가 아니면 setState를 호출하는 것은 오류입니다.

bool get mounted => _element != null;
  1. initState () -위젯이 생성 될 때 호출되는 첫 번째 메서드입니다 (물론 클래스 생성자 이후).

initState한 번만 호출됩니다. 전화해야합니다super.initState().

  • 위젯의 생성 된 인스턴스에 대한 특정 BuildContext에 의존하는 데이터를 초기화합니다.

  • 트리에서 이러한 위젯 ‘부모’에 의존하는 속성을 초기화합니다.

  • ChangeNotifiers이 위젯의 ​​데이터를 변경할 수있는 Streams, 또는 기타 개체를 구독합니다 .

@override
initState() {
  super.initState();
  // Add listeners to this class
  cartItemStream.listen((data) {
    _updateWidget(data);
  });
}
  1. didChangeDependencies () -이 State 객체의 종속성이 변경 될 때 호출됩니다.
  • 이 메서드는 initState. BuildContext.inheritFromWidgetOfExactType이 메서드에서 호출 하는 것이 안전합니다 .

  • 프레임 워크는 종속성 변경 후 항상 빌드를 호출하기 때문에 서브 클래스는이 메서드를 거의 재정의하지 않습니다. 일부 하위 클래스는 종속성이 변경 될 때 비용이 많이 드는 작업 (예 : 네트워크 가져 오기)을 수행해야하고이 작업이 모든 빌드에 대해 수행하기에는 너무 비싸기 때문에이 메서드를 재정의합니다.

@protected
@mustCallSuper
void didChangeDependencies() { }
  1. build () -위젯이 나타내는 사용자 인터페이스의 일부를 설명합니다.

프레임 워크는 다양한 상황에서이 메서드를 호출합니다.

  • 전화 후 initState.
  • 전화 후 didUpdateWidget.
  • 로 전화를받은 후 setState.
  • 이 State 개체의 종속성이 변경된 후 (예 : 이전 빌드 변경에서 참조 된 InheritedWidget).
  • 비활성화를 호출 한 후 다른 위치의 트리에 State 개체를 다시 삽입합니다.
  • 프레임 워크는이 메서드에서 반환 된 위젯이 기존 하위 트리의 루트를 업데이트 할 수 있는지 여부에 따라 기존 하위 트리를 업데이트하거나 하위 트리를 제거하고 새 하위 트리를 확장하여이 위젯 아래의 하위 트리를이 메서드에서 반환 된 위젯으로 바꿉니다. 를 호출하여 결정됩니다
    Widget.canUpdate.

  • 일반적으로 구현은이 위젯의 ​​생성자, 지정된 BuildContext 및이 State 객체의 내부 상태의 정보로 구성된 새로 생성 된 위젯 집합을 반환 합니다.

@override
  Widget build(BuildContext context, MyButtonState state) {
    ... () { print("color: $color"); } ...
  }
  1. didUpdateWidget () -위젯 구성이 변경 될 때마다 호출됩니다.
  • 상위 위젯이 동일한 런타임 유형 및 Widget.key를 가진 새 위젯을 표시하도록 트리의이 위치 업데이트를 다시 빌드하고 요청하는 경우 프레임 워크는이 State 개체의 위젯 속성을 업데이트하여 새 위젯을 참조한 다음이를 호출합니다. 이전 위젯을 인수로 사용하는 메서드.

  • 위젯이 변경 될 때 (예 : 암시 적 애니메이션 시작) 응답하도록이 메서드를 재정의합니다.

  • 프레임 워크는 항상 didUpdateWidget을 호출 한 후 build를 호출합니다. 즉, didUpdateWidget의 setState에 대한 모든 호출이 중복됩니다.

@mustCallSuper
@protected
void didUpdateWidget(covariant T oldWidget) { }
  1. setState ()-State 객체의 내부 상태를 변경할 때마다 전달하는 함수를 변경합니다 setState.
  • setState를 호출 하면이 개체의 내부 상태가이 하위 트리의 사용자 인터페이스에 영향을 줄 수있는 방식으로 변경되었음을 프레임 워크에 알립니다. 이로 인해 프레임 워크는
    이 State 개체에 대한 빌드를 예약 합니다.

  • setState 를 호출하지 않고 상태를 직접 변경하면 프레임 워크가 빌드를 예약하지 않을 수 있으며이 하위 트리의 사용자 인터페이스가 새 상태를 반영하도록 업데이트되지 않을 수 있습니다.

setState(() { _myState = newValue });
  1. deactivate () -Deactivate는 State가 트리에서 제거 될 때 호출되지만 현재 프레임 변경이 완료되기 전에 다시 삽입 될 수 있습니다. 이 방법은 기본적으로 State 객체를 트리의 한 지점에서 다른 지점으로 이동할 수 있기 때문에 존재합니다.
  • 프레임 워크는 트리에서이 State 개체를 제거 할 때마다이 메서드를 호출합니다. 어떤 경우에는 프레임 워크가 State 객체를 트리의 다른 부분에 다시 삽입합니다 (예 :이 State 객체를 포함하는 하위 트리가 트리의 한 위치에서 다른 위치로 접목 된 경우). 이 경우 프레임 워크는 빌드를 호출하여 State 개체가 트리의 새 위치에 적응할 수있는 기회를 제공하도록합니다. 프레임 워크가이 하위 트리를 다시 삽입하면 하위 트리가 트리에서 제거 된 애니메이션 프레임이 끝나기 전에 삽입됩니다. 이러한 이유로 State 개체는 프레임 워크가 해당 dispose 메서드를 호출 할 때까지 대부분의 리소스 해제를 연기 할 수 있습니다.

이것은 거의 사용되지 않습니다.

@protected
@mustCallSuper
void deactivate() { }
  1. dispose () -이 객체가 트리에서 영구적으로 제거 될 때 호출됩니다.
  • 프레임 워크는이 State 개체가 다시 빌드되지 않을 때이 메서드를 호출합니다. 프레임 워크 호출 후dispose() State 객체는 마운트 해제 된 것으로 간주되고 마운트 된 속성은 false입니다. 이 시점에서 setState를 호출하는 것은 오류입니다. 이 수명주기 단계는 최종 단계입니다. 폐기 된 상태 개체를 다시 탑재 할 방법이 없습니다.

  • 서브 클래스는이 객체가 보유한 모든 리소스를 해제하기 위해이 메서드를 재정의해야합니다 (예 : 활성 애니메이션 중지).

@protected
@mustCallSuper
void dispose() {
  assert(_debugLifecycleState == _StateLifecycle.ready);
  assert(() { _debugLifecycleState = _StateLifecycle.defunct; return true; }());
}

여기에 이미지 설명 입력

자세한 내용 여기 , 여기 로 이동 하십시오.


답변

flutter.io 의 문서에서 :

… 여기서 주목해야 할 중요한 점은 Stateless 및 Stateful 위젯이 모두 동일하게 작동한다는 점입니다. 그들은 모든 프레임을 다시 빌드하는데, 차이점은 StatefulWidget이 여러 프레임에 걸쳐 상태 데이터를 저장하고 복원하는 State 개체가 있다는 것입니다.

확실하지 않은 경우 항상 다음 규칙을 기억하십시오. 위젯이 변경되면 (예 : 사용자가 위젯과 상호 작용하는 경우) 상태 저장입니다. 그러나 자식이 변경에 반응하는 경우 부모가 변경에 반응하지 않으면 포함하는 부모가 여전히 Stateless 위젯이 될 수 있습니다.


답변

Flutter 문서에서 언급했듯이

점은 무엇인가?

일부 위젯은 상태 저장이고 일부는 상태 비 저장입니다. 위젯이 변경되면 (예 : 사용자가 위젯과 상호 작용) 상태 저장입니다. 위젯의 상태는 슬라이더의 현재 값 또는 확인란 선택 여부와 같이 변경할 수있는 값으로 구성됩니다. 위젯의 상태는 상태 개체에 저장되어 위젯의 상태와 모양을 구분합니다. 위젯의 상태가 변경되면 상태 객체는 setState ()를 호출하여 프레임 워크에 위젯을 다시 그리도록 지시합니다.

무 위젯은 관리 할 내부 상태가 없습니다. Icon, IconButton 및 Text는 StatelessWidget의 하위 클래스 인 상태 비 저장 위젯의 예입니다.

상태 위젯 동적이다. 사용자는 상태 저장 위젯과 상호 작용하거나 (예 : 양식에 입력하거나 슬라이더를 이동하여) 시간에 따라 변경 될 수 있습니다 (데이터 피드로 인해 UI가 업데이트 될 수 있음). Checkbox, Radio, Slider, InkWell, Form 및 TextField는 StatefulWidget의 하위 클래스 인 상태 저장 위젯의 예입니다.

https://flutter.io/tutorials/interactive/#stateful-stateless


답변

상태는 (1) 위젯이 빌드 될 때 동 기적으로 읽을 수 있고 (2) 위젯의 수명 동안 변경 될 수있는 정보입니다. State.setState를 사용하여 이러한 상태가 변경 될 때 State가 즉시 알림을 받도록하는 것은 위젯 구현 자의 책임입니다.

StatefulWidget :

상태 저장 위젯은 사용자 인터페이스를보다 구체적으로 설명하는 다른 위젯 집합을 구축하여 사용자 인터페이스의 일부를 설명하는 위젯입니다. 빌드 프로세스는 사용자 인터페이스의 설명이 완전히 구체화 될 때까지 반복적으로 계속됩니다 (예 : 구체적인 RenderObject를 설명하는 RenderObjectWidgets로 완전히 구성됨).

상태 저장 위젯은 설명하는 사용자 인터페이스 부분이 동적으로 변경 될 수있는 경우에 유용합니다. 예를 들어 내부 시계 구동 상태가 있거나 일부 시스템 상태에 따라 달라집니다. 개체 자체의 구성 정보와 위젯이 확장되는 BuildContext에만 의존하는 컴포지션의 경우 StatelessWidget을 사용하는 것이 좋습니다.

StatefulWidget 인스턴스 자체는 변경 불가능하며 createState 메서드에 의해 생성 된 별도의 State 객체 또는 State가 구독하는 객체 (예 : Stream 또는 ChangeNotifier 객체)에 변경 가능한 상태를 저장합니다.이 객체에 참조가 StatefulWidget의 최종 필드에 저장됩니다. 그 자체.

StatelessWidget :

상태 비 저장 위젯은 사용자 인터페이스를보다 구체적으로 설명하는 다른 위젯 집합을 구축하여 사용자 인터페이스의 일부를 설명하는 위젯입니다. 빌드 프로세스는 사용자 인터페이스의 설명이 완전히 구체화 될 때까지 반복적으로 계속됩니다 (예 : 구체적인 RenderObject를 설명하는 RenderObjectWidgets로 완전히 구성됨).

상태 비 저장 위젯은 설명하는 사용자 인터페이스의 일부가 개체 자체의 구성 정보와 위젯이 확장 된 BuildContext에 의존하지 않을 때 유용합니다. 예를 들어 내부 클럭 구동 상태가 있거나 일부 시스템 상태에 따라 동적으로 변경 될 수있는 컴포지션의 경우 StatefulWidget을 사용하는 것이 좋습니다.


답변

Stateless 위젯 은 정적 위젯입니다. Stateless 위젯을 초기화하기 전에 몇 가지 속성 만 전달하면됩니다. 데이터 변경이나 동작 변경에 의존하지 않습니다. 예를 들어. Text, Icon, RaisedButton은 Stateless 위젯입니다.

상태 저장 위젯 은 동적 위젯이며 사용자 작업 또는 데이터 변경에 따라 런타임 중에 업데이트 될 수 있습니다. 위젯이 런타임 중에 상태를 변경할 수 있으면 상태 저장 위젯이됩니다.

2018 년 11 월 15 일 수정

Stateless 위젯 은 입력 / 외부 데이터가 변경되면 다시 렌더링 할 수 있습니다 (외부 데이터는 생성자를 통해 전달되는 데이터 임). 상태 비 저장 위젯에는 상태가 없기 때문에 한 번 렌더링되고 자체적으로 업데이트되지 않지만 외부 데이터가 변경 될 때만 업데이트됩니다.

반면 스테이트 위젯 내부 상태가 상기 입력 데이터를 변경 또는 위젯의 상태가 변경 될 경우, 만약 재 렌더링 할 수있다.

상태 비 저장 및 상태 저장 위젯 모두 수명주기가 다릅니다.


답변

저는 아주 간단한 비유를 생각할 수 있습니다. 책, 장식, TV가있는 가구가 있습니다. 가구는 무국적 상태로 움직이지 않습니다. TV에서는 다른 쪽에서 켜기, 끄기, 채널 변경, DVD가 연결되어있는 경우 영화 재생 등을 수행 할 수 있습니다. TV에는 동작 방식에 영향을주는 내부 상태가 있습니다. 가구에는 상태가 없습니다. 가구에 TV가 있다고해서 상태가 추가되는 것은 아닙니다. 도움이 되었기를 바랍니다.