iT邦幫忙

2021 iThome 鐵人賽

DAY 2
2
Mobile Development

Flutter - 複製貼上到開發套件之旅系列 第 2

【第二天 - Flutter 繼承+建構子+CallBack 基本概念】

前言

今日的程式碼 => GITHUB

繼承

Flutter 會有三個方式

  1. Extends
  • 當繼承 Extends 的時候,需要使用 super 來繼承父類別的 method.
  • 繼承一次只能繼承一個父親類別
  • 建構函數不能繼承
  • 調用父類別的 method 需要使用 super
  • 可以覆寫父親類別的 method
 @override
 void animal() {
   // TODO: implement animal
   super.animal();
 }
  1. With
  • 可以直接使用父親的 method
  • 可以混合很多個
  1. implements
  • class 就是 interface
  • 需要實作介面。
  • 可以實作很多個介面
class Animal {
  void animal() {}
}

class Fly {
  String className = "carton";

  void fly() {}
}

class Swim {
  void swimming() {}
}

class Eat {
  void eat() {}
}

class Draink {
  void drink() {}
}

class AAA extends Animal with Eat, Draink implements Fly, Swim {
  @override
  String className = "AAA";

  void turnOn() {
    super.animal();
    _test();
    eat();
    drink();
  }

  void _test() {}

  @override
  void fly() {
    // TODO: implement Fly
  }

  @override
  void swimming() {
    // TODO: implement Swim
  }
}

建構子

StatelessWidget

  1. 給予預設值(可以傳參數,也可以不傳)
class MyWidget extends StatelessWidget {
  
  final String title;
  
  const MyWidget({Key? key, this.title = 'abc'}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Text(title);
  }
}
MyWidget(title: 'cc'), // 顯示 cc 
MyWidget(), // 顯示 abc
  1. Required(被要求一定要傳參數)
class MyWidget extends StatelessWidget {

  final String title;

  const MyWidget({Key? key,required this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Text(title);
  }
}
MyWidget(title: 'cc'), // 顯示 cc 
  1. 私有化的參數
class MyWidget extends StatelessWidget {

  final String _title;

  const MyWidget({String title = '3'}) : _title = title;
  // const MyWidget({required String title}) : _title = title;

  @override
  Widget build(BuildContext context) {
    return Text(_title);
  }
}

StatefulWidget

  1. 給予預設值(可以傳參數,也可以不傳)
class MyWidget extends StatefulWidget {

  final String title;

  const MyWidget({Key? key, this.title = 'abc'}) : super(key: key);

  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  @override
  Widget build(BuildContext context) {
    return Text(widget.title);
  }
}
MyWidget(title: 'cc'), // 顯示 cc 
MyWidget(), // 顯示 abc
  1. Required(被要求一定要傳參數)
class MyWidget extends StatefulWidget {

  final String title;

  const MyWidget({Key? key,required this.title}) : super(key: key);

  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  @override
  Widget build(BuildContext context) {
    return Text(widget.title);
  }
}
MyWidget(title: 'cc'), // 顯示 cc 
  1. 私有化的參數
class MyWidget extends StatefulWidget {

  final String _title;

  const MyWidget({String title = '3'}) : _title = title;

  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  @override
  Widget build(BuildContext context) {
    return Text(widget._title);
  }
}

CallBack

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: TextView(
        callback: (String text) => _showDialog(context, text)),
    );
  }

  void _showDialog(BuildContext context, String text) {
    showDialog<void>(
        context: context, builder: (context) => AlertDialog(title: Text(text)));
  }
}

class TextView extends StatefulWidget {
  const TextView({required this.callback});

  final void Function(String text) callback;

  @override
  _TextViewState createState() => _TextViewState();
}

class _TextViewState extends State<TextView> {
  final _controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        TextFormField(controller: _controller),
        IconButton(
          onPressed: () async => widget.callback(_controller.text),
          icon: Icon(Icons.check),
        )
      ],
    );
  }
}

我們現在假設有一個情境:

  • 我的子元件是一個輸入匡,我的父元件是一個 Scaffold,裡面有一個 showDialog 的 method
  • 今天我需要在父元件裡面取得子元件輸入匡的文字傳給 showDailog。
  1. 確定我們關鍵參數是什麼。是輸入匡的文字。因此在 TextView 這個 class 裡面建立一個 function
final void Function(String text) callback;
final Function callback; // 這樣也可以,但是不建議,因為這樣很難 DeBug
  1. 並要求父元件一定要有這個方法
const TextView({required this.callback});
  1. 接著我們在按鈕的 onPressed call 這個 function
onPressed: () async => widget.callback(_controller.text),
  1. 當我們在父親元件使用 TextView 這個子元件時,callback 裡面的 text 就是我們子元件輸入匡的 text 了。
TextView(callback: (String text) {  },),

上一篇
【第一天 - Flutter 生命週期+基本觀念介紹】
下一篇
【第三天 - Flutter Route 規劃分享】
系列文
Flutter - 複製貼上到開發套件之旅30

1 則留言

0
SKYDOG
iT邦新手 5 級 ‧ 2021-09-16 23:55:35

讚哦/images/emoticon/emoticon12.gif

我要留言

立即登入留言