위젯을 만드는 함수와 클래스의 차이점은 무엇입니까?
StatelessWidget 을 서브 클래 싱하는 대신 일반 함수를 사용하여 위젯을 만들 수 있다는 것을 깨달았습니다 . 예를 들면 다음과 같습니다.
Widget function({ String title, VoidCallback callback }) {
return GestureDetector(
onTap: callback,
child: // some widget
);
}
이것은 본격적인 클래스보다 훨씬 적은 코드가 필요하기 때문에 흥미 롭습니다 . 예:
class SomeWidget extends StatelessWidget {
final VoidCallback callback;
final String title;
const SomeWidget({Key key, this.callback, this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: callback,
child: // some widget
);
}
}
그래서 저는 궁금했습니다. 위젯을 만드는 함수와 클래스 사이에 구문 외에 다른 점이 있습니까? 함수를 사용하는 것이 좋은 습관입니까?
요약 : 재사용 가능한 위젯 트리를 만들기 위해 클래스보다 함수를 사용하지 마십시오 . 대신 항상 StatelessWidget 으로 추출하십시오 .
클래스 대신 함수를 사용 하는 것에는 큰 차이가 있습니다. 즉, 프레임 워크는 함수를 인식하지 못하지만 클래스를 볼 수 있습니다.
다음 "위젯"기능을 고려하십시오.
Widget functionWidget({ Widget child}) {
return Container(child: child);
}
이 방법으로 사용 :
functionWidget(
child: functionWidget(),
);
그리고 그것은 동등한 클래스입니다.
class ClassWidget extends StatelessWidget {
final Widget child;
const ClassWidget({Key key, this.child}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
child: child,
);
}
}
다음과 같이 사용 :
new ClassWidget(
child: new ClassWidget(),
);
서류상 둘 다 똑같은 일을하는 것 같습니다 : Create 2 Container
, 하나는 다른 하나에 중첩됩니다. 그러나 현실은 약간 다릅니다.
함수의 경우 생성 된 위젯 트리는 다음과 같습니다.
Container
Container
클래스를 사용하는 동안 위젯 트리는 다음과 같습니다.
ClassWidget
Container
ClassWidget
Container
이는 위젯을 업데이트 할 때 프레임 워크가 작동하는 방식을 근본적으로 변경하기 때문에 매우 중요합니다. 다음은 선별 된 차이점 목록입니다.
클래스:
- 성능 최적화 허용 (const 생성자, 연산자 == 재정의,보다 세분화 된 재 빌드)
- 핫 리로드
- 위젯 인스펙터 (debugFillProperties)에 통합됩니다.
- 키를 정의 할 수 있습니다.
- 컨텍스트 API를 사용할 수 있습니다.
- 모든 위젯이 동일한 방식으로 사용되는지 확인 (항상 생성자)
- 서로 다른 두 레이아웃 사이를 전환하면 리소스가 올바르게 처리되는지 확인합니다 (함수는 이전 상태를 재사용 할 수 있음).
기능 :
- 코드가 적습니다 (그리고 거기에서도 클래스를 함수만큼 작게 만드는 코드 생성기를 만들었습니다 : functional_widget )
- ?
결론은 이미 매우 명확해야합니다.
위젯을 만드는 데 함수를 사용하지 마십시오 .
이 문제에 대해 지난 2 일 동안 조사했습니다. 저는 다음과 같은 결론에 도달했습니다. 앱의 일부를 기능으로 나누는 것은 괜찮습니다. 이러한 함수가를 반환하는 것이 이상적 StatelessWidget
이므로를 만드는 것과 같은 최적화를 수행 할 수 StatelessWidget
const
있으므로 필요하지 않은 경우 다시 빌드하지 않습니다. 예를 들어 다음 코드는 완벽하게 유효합니다.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
++_counter;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
const MyWidgetClass(key: const Key('const')),
MyWidgetClass(key: Key('non-const')),
_buildSomeWidgets(_counter),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
Widget _buildSomeWidgets(int val) {
print('${DateTime.now()} Rebuild _buildSomeWidgets');
return const MyWidgetClass(key: Key('function'));
// This is bad, because it would rebuild this every time
// return Container(
// child: Text("hi"),
// );
}
}
class MyWidgetClass extends StatelessWidget {
const MyWidgetClass({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
print('${DateTime.now()} Rebuild MyWidgetClass $key');
return Container(
child: Text("hi"),
);
}
}
함수를 사용하면 const StatelessWidget
. 내가 틀렸다면 나를 고쳐주세요.
Flutter 위젯을 호출 할 때 const 키워드를 사용해야합니다. 예를 들면const MyListWidget();
'programing' 카테고리의 다른 글
최신 브라우저에서 파일을 업로드하는 가장 좋은 방법은 무엇입니까? (0) | 2020.11.28 |
---|---|
Angular 2 구성 요소 속성의 기본값을 설정하는 방법은 무엇입니까? (0) | 2020.11.28 |
Eclipse의 문제보기에 대한 모범 사례 (0) | 2020.11.27 |
MySQL : 많은 테이블 또는 많은 데이터베이스? (0) | 2020.11.27 |
argc가 'unsigned int'가 아닌 'int'인 이유는 무엇입니까? (0) | 2020.11.27 |