[Flutter] StatelessWidget VS StatefulWidget

Visarut Junsone
Lazy-Dev
Published in
2 min readFeb 16, 2019

เอาละกลับมาอีกครั้งในหัวข้อ Flutter ครั้งที่ผ่านมาผมได้พูดเรื่อง [Flutter] Getting Started. ไป หลังจากมีโค้ดเริ่มต้นแล้วเราก็ดำเนินการอย่างอื่นต่อได้อย่างง่ายดาย แล้วจะทำอะไรต่อไปละ ก็ต้องทำหน้า Login page สิ โดยตัวอย่างใน blog นี้จะเป็นการทำ Login page แต่สิ่งที่เราจะพูดถึงหลัก ก็คือ StatelessWidget และ StatefulWidget ว่ามันต่างกันยังไง

StatelessWidget

จากหัวข้อแรก [Flutter] Getting Started. ได้มีการใช้ StatelessWidget เพื่อทำ Widget อย่างง่ายขึ้นมา แล้วมันคืออะไรละ แล้วเหมาะกับการใช้งานต่อไหน StatelessWidget คือ widget ที่ไม่มีการทำ state เพื่อใช้เป็นตัวเชื่อมกับกลุ่ม widget ตัวอื่นๆ ตัวอย่างเช่น MyApp ในตัวอย่างแรก ที่เป็น StatelessWidget นั้น ไม่มีการทำ state ใดๆ และนำมาสร้างเพื่อเป็นจุดเชื่อมไป widget อื่นๆ ในกรณีนี้คือ MyStatelessWidget

ซึ่ง StatelessWidget นั้นทำการสร้าง widget นั้น ว่ากันง่าย ๆ เลยก็คือ จะ render เหมือนเดิมเสมอ เช่น render แสดงแค่ Text “Hello world” ไม่ว่าจะเปิดหน้านี้มาใหม่ยังไงก็เหมือนเดิม

StatefulWidget

เปิด Code ตัวอย่างได้ที่ LoginPage Flutter Basic

StatefulWidget นั้นจะมีความแตกต่างจาก StatelessWidget widget เล็กน้อย แต่มีสิ่งที่เสริมมาก็คือ การใช้ Event เพื่อเปลี่ยนแปลงค่า State เพื่อที่จะ trigger และ rebuild widget นั้นๆ ใหม่อีกครั้งหนึ่ง ในกรณีนี้ก็คือ _user , _password และ message บางอย่างที่จะเอาไว้บอกผู้ใช้

class LoginPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final formKey = GlobalKey<FormState>();
String _user;
String _password;
bool validateAndSave() {
final form = formKey.currentState;
if (form.validate()) {
form.save();
return true;
} else {
return false;
}
}
void validateAndSubmit() {
if(validateAndSave()) {
}
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
body: Center(
child: Container(
padding: EdgeInsets.all(10.0),
child: Form(
key: formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
'LAZYDEV',
style: TextStyle(
fontWeight: FontWeight.w700, fontSize: 50.0),
),
Text(
'LAZY IS GOOD',
style: TextStyle(
fontWeight: FontWeight.normal, fontSize: 33.0),
),
Padding(
padding: EdgeInsets.all(30.0),
),
TextFormField(
validator: (value) =>
value.isEmpty ? 'Email can\'t be empty' : null,
onSaved: (value) => _user = value,
decoration: InputDecoration(
labelText: 'User',
border: new OutlineInputBorder(
borderRadius: const BorderRadius.all(
const Radius.circular(50.0),
),
),
hintStyle: new TextStyle(color: Colors.grey[800]),
),
),
Padding(
padding: EdgeInsets.all(10.0),
),
TextFormField(
onSaved: (value) => _password = value,
validator: (value) =>
value.isEmpty ? 'Password can\'t be empty' : null,
decoration: InputDecoration(
labelText: 'Password',
border: new OutlineInputBorder(
borderRadius: const BorderRadius.all(
const Radius.circular(50.0),
),
),
hintStyle: new TextStyle(color: Colors.grey[800]),
),
obscureText: true,
),
Padding(
padding: EdgeInsets.all(20.0),
),
ButtonTheme(
minWidth: 140.0,
height: 50.0,
child: RaisedButton(
color: Colors.grey,
onPressed: validateAndSubmit,
child: Text(
'Login',
style: TextStyle(fontSize: 20.0, color: Colors.white),
),
shape: RoundedRectangleBorder(
borderRadius: const BorderRadius.all(
const Radius.circular(50.0),
),
),
),
),
],
)))));
}
}

จากโค้ดตัวอย่างจะเห็นได้ว่ามีการใช้ event onSaved และ onPressed ซึ่งที่ onSaved นั้นก็ทำการเปลี่ยนค่า _user และ _password. และมี onPressed ซึ่งจะ trigger เมื่อผู้ใช้กดปุ่ม เพื่อเรียก validateAndSubmit ที่เรียก validateAndSave อีกทีหนึ่ง โดยใน validateAndSave มีคำสั่ง form.validate() เพื่อจะ trigger validator ให้ตรวจสอบค่า _user และ _password เมื่อ validate ไม่ผ่าน จะทำการ render คำอธิบาย error ด้านล่าง TextField

--

--

Visarut Junsone
Lazy-Dev

I’m Full-Stack Developer. ReactJS Golang C# Javascript C++ PHP and learning a lot more. Not lazy as it name. “Lazy-Dev”