ارتباط بین ویجت ها با استفاده از انواع callback در فلاتر


چرا این بحث مهمه؟ چون به ما اجازه میده که ویجت هامون رو به قسمت های کوچک تری تبدیل کنیم که به راحتی قابل تست و ویرایش باشن و بتونن با بخش اصلی به راحتی سازگار بشن.


ساختن یک پروژه جدید

مثل همیشه با راه اندازی یک پروژه جدید شروع میکنیم :

# New Flutter project
$ flutter create widget_communication
# Open this up inside of VS Code
$ cd widget_communication && code .

حالا پروژه رو توی VS Code یا Android studio باز میکنیم.

اماده کردن بیس پروژه

اول باید بیس پروژمون رو خیلی ساده ایجاد کنیم. برای این کار وارد main.dart میشیم و این فایل رو اپدیت میکنیم به وسیله دادن رفرنس به CounterPage که جلوتر میسازیمش

import 'package:flutter/material.dart';
import 'package:widget_communication/counter_page.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
    Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Widget Communication',
            home: CounterPage(),
                );
    }
 }

صفحه CounterPage ما یه StatefulWidget ساده هست :

// counter_page.dart
import 'package:flutter/material.dart';
import 'package:widget_communication/count.dart';

class CounterPage extends StatefulWidget {
  _CounterPageState createState() => _CounterPageState();
}

class _CounterPageState extends State<CounterPage> {
  int count = 0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(&quotWidget Communication&quot)),
      body: Center(
        child: Count(count),
      ),
    );
  }
}

اگر توجه کنید داخل این ویجت ما یه متغیر count داریم که برابر با 0 هست و پاسش دادیم به یه ویجت تحت عنوان Count به صورت property . حالا میریم سراغ ویجت Count :

// count.dart
import 'package:flutter/material.dart';

class Count extends StatelessWidget {
  final int count;

  Count(this.count);

  @override
  Widget build(BuildContext context) {
    return Text(&quot$count&quot);
  }
}

این چیزیه که تا حالا ساختیم

شروع با VoidCallback

برای این مثال متغیر count رو داخل داخل یه دکمه میزاریم و بهش میگیم هر وقت روت کلیک شد باید کلاس پدرت که CounterPage هست رو صدا بزنی.

ما اینجا هیچ مقداری رو نمیخوایم بفرستیم، پس شروع میکنیم به راه اندازی VoidCallback و اسمش رو onCountSelected میزاریم :

// count.dart
class Count extends StatelessWidget {
  final int count;
  final VoidCallback onCountSelected;

  Count({@required this.count, this.onCountSelected});

  @override
  Widget build(BuildContext context) {
    return FlatButton(
      child: Text(&quot$count&quot),
      onPressed: () => onCountSelected(),
    );
  }
}


حالا باید اپدیت کنیم CounterPage رو تا گوش بده به کال بک onCountSelected:

// counter_page.dart
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: Text(&quotWidget Communication&quot)),
    body: Center(
      child: Count(
        count: count,
        onCountSelected: () {
          print(&quotCount was selected.&quot);
        },
      ),
    ),
  );
}

حالا هر وقت ما روی counter کلیک کنیم باید Count was selected رو توی کنسول ببینیم.


ادامه دادن با (Function(x

همینجوری که دیدید VoidCallback میتونه عالی باشه وقتی که قرار نباشه مقداری برگردونده بشه، اما اگر ما بخوایم مقدار برگردونیم چی؟

اینجاست که (Function(x وارد میشه:

// counter_page.dart
import 'package:flutter/material.dart';

class Count extends StatelessWidget {
  final int count;
  final VoidCallback onCountSelected;

  final Function(int) onCountChange;

  Count({
    @required this.count,
    @required this.onCountChange,
    this.onCountSelected,
  });

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        IconButton(
          icon: Icon(Icons.add),
          onPressed: () {
            onCountChange(1);
          },
        ),
        FlatButton(
          child: Text(&quot$count&quot),
          onPressed: () => onCountSelected(),
        ),
        IconButton(
          icon: Icon(Icons.remove),
          onPressed: () {
            onCountChange(-1);
          },
        ),
      ],
    );
  }
}

اینجا ما دو تا دکمه اظافه کردیم همراه با یه (Function(int به نام onCountChange که وقتی ما صداش بزنیم یک مقدار رو به ویجت پدرش برمیگردونه.

توی ویجت پدر هم ما شروع به گوش دادن میکنیم هر وقت مقداری اومد count رو اپدیت میکنیم.

class _CounterPageState extends State<CounterPage> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(&quotWidget Communication&quot)),
      body: Center(
        child: Count(
          count: count,
          onCountSelected: () {
            print(&quotCount was selected.&quot);
          },
          onCountChange: (int val) {
            setState(() => count += val);
          },
        ),
      ),
    );
  }
}

نتیجه نهایی:

امیدوارم که درست شیوه کار کال بک ها رو یاد گرفته باشید. موفق باشید.