Stateful Widget의 life cycle

[Flutter] Widget의 Life cycle

1. initState

플러터나 위젯의 라이프 사이클을 몰라도 익숙한 함수이다.
해당 위젯이 로드 될때 필요한 초기화를 진행하게 된다.
빌드 이전에 한번만 실행되며 안드로이드 스튜디오의 onCreate
유니티의 Awake 함수에 해당한다.

2. didChangeDependencies

initState직후에 호출된다.
또한 InheritedWidget으로부터 종속된 경우 그 위젯이 변경될때 다시 호출된다.

3. build

라이프 사이클을 통틀어 가장 중요한 부분으로 여기에서 위젯을 렌더링한다.
didChangeDependencies 이후 호출되며 다시 그리는 비용이 저렴하다.
UI를 렌더링 할때마다 호출된다.

4. didUpdateWidget

자주 접하게 될 라이프 사이클은 아니지만 상위 위젯이 변경되고
UI를 다시 그려야 할 때 호출된다.
파라미터로 oldWidget을 가져오고 현재 위젯과 비교하여 추가논리를 수행 할 수 있다.

5. dispose

initState와 반대의 라이프 사이클로 해당 개체가
위젯트리에서 영구적으로 제거되고 다시 빌드되지 않을 때 호출된다.
여기선 스트림을 구독 취소하거나 애니메이션을 삭제하는 등의 일을 하게된다.

build 이후에 한번만 실행

가령 처음에 위젯을 하나 생성후에 애니메이션을 재생시키고 싶다면
위의 라이프 사이클로는 수행 하기 어렵다.
하지만 방법이 있으니 바로 initState함수에 addPostFrameCallback함수를 호출 하는것이다.

1
2
3
4
5
  void initState() {
    super.initState();
    WidgetsBinding.instance
        .addPostFrameCallback((_) => yourFunction(context));
  }
cs

참고

라이프 사이클 : https://medium.com/flutter-community/flutter-lifecycle-for-android-and-ios-developers-8f532307e0c7

 

Flutter Lifecycle for Android and iOS Developers

One of the most confusing ideas transitioning from Android and/or iOS is to understand how Flutter handles its lifecycle.

medium.com

addPostFrameCallback : https://stackoverflow.com/questions/49466556/flutter-run-method-on-widget-build-complete

 

Flutter: Run method on Widget build complete

I would like to be able to run functions once a Widget has finished building/loading but I am unsure how. My current use case is to check if a user is authenticated and if not, redirect to a login...

stackoverflow.com

 

여기선 List에 위젯들을 추가 후 remove로 삭제할때 작동하지 않는 경우를 메모한다.

 

1. 현상

List<Widget>을 선언 한 후 add함수로 필요한 위젯들을 추가 하였다.

그리고 builder 팩토리 생성자로 리스트의 위젯들을 빌드하여 사용자에게 보여준다.

또한 동적으로 삭제도 할 수 있으며 setState함수에서 remove함수를 호출하였다.

하지만 리스트에서 아이템이 삭제가 되지않았다..

 

2. 해결

리스트의 remove함수가 아닌 removeWhere함수를 이용하라는 검색결과가 있었다.

사용방법은 C#에서 자주 사용한 Linq식과 똑같이 removeWhere((파라미터)=>판별식);

과 같이 사용하면 되고 이렇게 사용하는 편이 요소를 지정하는데 애매하지 않고 확실하다고 생각한다.

나는 각 요소에 key값을 주어 이 key값을 비교해 삭제하는 판별식을 작성하였다.

 

참고 : https://stackoverflow.com/questions/66314111/how-to-remove-an-element-from-list-of-widgets-in-flutter/66315505

 

How to remove an element from List of Widgets in flutter?

I made a list of TableRows in flutter whichI passed as a children to my Table widget .Each row has some data and a flat button at the end which deletes the data from by database and I want to delet...

stackoverflow.com

 

1. 객체지향언어에서의 상속

객체지향언어에서는 코드의 재사용성을 위해 상속을 사용하기도 한다.

실제로 라이브러리의 유용한 클래스를 상속받아 프로젝트에 맞게 커스터마이징을 한 후 사용하기도 한다.

 

2. 플러터의 구조

플러터는 기본적으로 위젯이라는 객체들로 구성되어있으며 하나의 위젯트리를 형성한다.

앱의 기본이 되는 MaterialApp과 Scaffold역시 위젯이며 이 위젯을 시작으로 수 많은 자식 위젯들로 하나의 앱이 완성된다.

플러터는 수 많은 위젯들을 준비하여 두었고 우리는 그 위젯들을 적재적소에 구성하기만 하면된다.

가령

가운데 정렬을 하고싶다 : Center 위젯

버튼을 삽입하고싶다 : ElevatedButton 위젯

이미지를 삽입하고싶다 : Image 위젯

가운데 정렬된 버튼 안에 이미지를 삽입하고싶다 : Center - ElevatedButton - Image

처럼말이다.

 

3. 위젯을 상속

프로젝트를 진행하다보면 프레임워크나 라이브러리에서 제공하는 위젯만 가지고는 필요한 기능이 부족할 수 도 있다.

그럴땐 보통 위의 설명과 같이 클래스를 상속받아 기능을 확장하는것이 일반적인데..

실제로 위젯을 상속받아 구현을 해보려고 했지만 생성자의 구성과 Null safty 로 인해 아무 기능도 확장도 하지않은 클래스가 이미 복잡해져버려서 정상적인 위젯의 상속방법을 찾아 검색에 나섰다.

기본적인 Dart 문법으로 상속을 하는 예제는 많았지만 이미 정의된 위젯을 상속받는 예제는 찾아 볼 수 없었고 그 대신 아래와 같은 글을 찾을 수 있었다.

https://stackoverflow.com/questions/51476234/subclass-a-class-that-extends-statelesswidget-or-statefulwidget-class

 

Subclass a class that extends StatelessWidget or StatefulWidget class

Is it possible to create a class that extends a class extending StatelessWidget or StatefulWidget. For example: class MyButton extends StatelessWidget { final String label; Button({this.label}); @

stackoverflow.com

https://flutter.dev/docs/resources/faq#can-i-extend-and-customize-the-bundled-widgets

 

FAQ

Frequently asked questions and answers about Flutter.

flutter.dev

 

Can I extend and customize the bundled widgets?

Absolutely. Flutter’s widget system was designed to be easily customizable.

Rather than having each widget provide a large number of parameters, Flutter embraces composition. Widgets are built out of smaller widgets that you can reuse and combine in novel ways to make custom widgets. For example, rather than subclassing a generic button widget, ElevatedButton combines a Material widget with a GestureDetector widget. The Material widget provides the visual design and the GestureDetector widget provides the interaction design.

To create a button with a custom visual design, you can combine widgets that implement your visual design with a GestureDetector, which provides the interaction design. For example, CupertinoButton follows this approach and combines a GestureDetector with several other widgets that implement its visual design.

Composition gives you maximum control over the visual and interaction design of your widgets while also allowing a large amount of code reuse. In the framework, we’ve decomposed complex widgets to pieces that separately implement the visual, interaction, and motion design. You can remix these widgets however you like to make your own custom widgets that have full range of expression.

 

4. 결론

위 글들의 결론은 플러터에서 이미 만들어진 위젯(StatelessWidget 또는 StatefulWidget위젯을 이미 상속받은 위젯)의 기능을 추가하기 위해 위젯을 상속 받는것이 불가능한것은 아니지만 상속이 아닌 구성을 추천한다는 것이다. 

이 방법이 익숙치는 않지만 mixin키워드와 같은 키워드와 더불어 원하는 위젯을 만드는데 어려움은 없어보인다

1. 소개

Dart가 Java나 C#같은 언어와 다르다고 느꼇던 부분이 다중상속을 지원하지 않는 것이다.

 

인터페이스는 지원하지만 각 클래스마다 내용을 구현해야하는 번거로움이 있을 것이다.

 

다음과 같이 부모클래스 이외에 다른 클래스의 메소드를 재사용 하고싶을때에는 어떻게 할까?

 

그림1. 상속관계 : 이걸 어떻게 구현할까?

 

그럴때 이 mixin 기능을 이용한다.

 

2. 언어적 표현

성기사를 한번 디자인 해보자.

Person 클래스를 구현하고, Person 클래스를 상속받은 Knight 클래스를 구현한다.

그리고 마지막으로 Knight를 상속받아 Holy knight를 구현한다.

기본적으로 OOP에서는 기본적으로 지원하는 선형적인 상속관계가 완성되었다.

그러나 재사용 가능성이 있는 Holy skills는 어떻게 구현하면 될까.

 

mixin대상이 될 (Holly skills) 클래스를 구현하고

이 클래스를 사용 할 (Holly Knight)클래스가 with 키워드로 mixin하면된다.

 

여기서 제한 사항이 하나 있는데 mixin의 대상이 될 클래스는 생성자를 선언하면 안된다는 것이다.

또한, 일반적인 방법으로 클래스를 사용하고 싶지않고 (인스턴스화 하거나 상속을 받게함)

mixin클래스로만 활용하고 싶다면 class 키워드 대신 mixin 키워드로 선언하자.

 

3. 구현

위의 내용을 구현한 코드는 아래와 같다.

 

abstract class Person{}

abstract class Knight extends Person{}

mixin HolySkills {
  void holySkill(){
  print('Holy Skill');
  }
}

class HolyKnight extends Knight with HolySkills{}

void main() {
  HolyKnight holyKnight = HolyKnight();
  holyKnight.holySkill();
}

+ Recent posts