iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 6
0
Mobile Development

Flutter 從零開始,Android、iOS一次搞定,重新挑戰。系列 第 6

[Day6] Flutter 將我們的專案全面套上 Provider。

還記得我們在 Day3-Day4 時介紹了一個狀態管理套件,今天我們就要把他套在我們的代辦清單啦~

首先我們先在 lib/providers/todos.dart 建立一個新的目錄與檔案:

import "package:flutter/foundation.dart";

class Todo with ChangeNotifier {
  final int id;
  final String title;
  final String description;
  bool done;

  Todo({this.id, this.title, this.description, this.done});

  void toggleDone() {
    done = !done;
    notifyListeners();
  }
}

class Todos with ChangeNotifier {
  List<Todo> _items = [
    Todo(id: 1, title: "Test1", description: "abc123", done: false),
    Todo(id: 2, title: "Test2", description: "abc123", done: false),
    Todo(id: 3, title: "Test3", description: "abc123", done: false),
    Todo(id: 4, title: "Test4", description: "abc123", done: true),
    Todo(id: 5, title: "Test5", description: "abc123", done: false),
    Todo(id: 6, title: "Test6", description: "abc123", done: true),
    Todo(id: 7, title: "Test7", description: "abc123", done: false),
    Todo(id: 8, title: "Test8", description: "abc123", done: false),
  ];

  List<Todo> get items {
    return [..._items];
  }

  void addTodo(Todo todo) {
    final newTodo = Todo(
      title: todo.title,
      description: todo.description,
      done: false,
    );
    // _items.add(newTodo);
    _items.insert(0, newTodo); // at the start of list
    notifyListeners();
  }

  void deleteTodo(int itemId) {
    final existingTodoIndex = _items.indexWhere((prod) => prod.id == itemId);
    // var existingTodo = _items[existingTodoIndex];
    _items.removeAt(existingTodoIndex);
    notifyListeners();
  }
}

把所有的狀態都搬到這裡,且會改變狀態的函式也全數搬過來,調整了一番邏輯之後就大功告成拉~
記得在改變狀態後需要加上 notifyListeners() ,讓使用這些狀態的組件可以監聽到變化哦~

接下來使用我們的Provider Widget把我們的 App 包起來:

import 'package:flutter/material.dart';
import './screens/todos_homepage.dart';
import 'package:provider/provider.dart';
import './providers/todos.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      builder: (_) => Todos(),
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: TodosHomepage(),
      ),
    );
  }
}

這樣子目錄就可以隨時使用Todos的方法,或狀態囉~
以下看看我們要怎麼在TodosHomepage取得Todos的狀態吧!

import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:provider/provider.dart';

import '../widgets/todo_tile.dart';
import '../screens/edit_todo_screen.dart';
import '../providers/todos.dart';

class TodosHomepage extends StatefulWidget {
  @override
  _TodosHomepageState createState() => _TodosHomepageState();
}

class _TodosHomepageState extends State<TodosHomepage> {
  final SlidableController slidableController = SlidableController();

  @override
  Widget build(BuildContext context) {
    final todosProvider = Provider.of<Todos>(context);
    return Scaffold(
      appBar: AppBar(
        title: Text('Todos'),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.add),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (ctx) => EditTodoScreen(),
                ),
              );
            },
          )
        ],
      ),
      body: ListView.builder(
        itemCount: todosProvider.items.length,
        itemBuilder: (ctx, i) => ChangeNotifierProvider.value(
          value: todosProvider.items[i],
          child: TodoTile(slidableController: slidableController),
        ),
      ),
    );
  }
}

我們可以使用 final todosProvider = Provider.of<Todos>(context);
這樣我們只需要,todosProvider.items 我們就可以拿到所有待辦清單的List。

然後我這邊又包了一個 ChangeNotifierProvider.value 把我們的一個一個的待辦清單分開丟到TodoTile
這樣我們就可以不用一個一個參數往裡面傳,且當done被更新我們也可以監聽的到,即時的改變渲染,是不是很棒啊!

最後的最後我們來看看我們的 lib/widgets/todo_tile.dart
我再想想看要怎麼解釋,今天就先這樣拉~
一樣附上我的原始碼:
https://github.com/kevinypfan/ithome-todo-project


上一篇
[Day5] Flutter 清單滑動選項添加。
下一篇
[Day7] Flutter Drawer 側邊導覽列。
系列文
Flutter 從零開始,Android、iOS一次搞定,重新挑戰。12

尚未有邦友留言

立即登入留言