Menu
CoddyTech

Kéo để làm mới

Thuộc phần Dữ liệu và mạng trong hành trình Flutter của Coddy. Bài học 9 trên 27.

Trên điện thoại, mọi người kéo danh sách xuống để tải lại. Biểu tượng xoay xuất hiện từ phía trên và dữ liệu được cập nhật. Widget Flutter dùng cho việc này là RefreshIndicator:

RefreshIndicator(
  onRefresh: refresh,
  child: ListView(
    children: [ ... ],
  ),
)

onRefresh là một hàm trả về Future. Biểu tượng xoay khi kéo vẫn hiển thị cho đến khi future đó hoàn tất, vì vậy hãy await dữ liệu mới bên trong hàm này:

Future<void> refresh() async {
  setState(() {
    _tip = fetch('/tip');
  });
  await _tip;
}

Thao tác kéo chỉ hoạt động trên nội dung có thể cuộn. Hãy đặt nội dung trong ListView, ngay cả khi chỉ có một phần tử: bạn luôn có thể kéo ListView xuống. Biểu tượng xoay khi kéo đã cho biết ứng dụng đang hoạt động, vì vậy builder có thể giữ gợi ý cũ bằng cách kiểm tra hasData.

challenge icon

Thử thách

Trung bình

Cho mẹo tải lại khi bạn kéo màn hình xuống:

  • thêm phương thức refresh để đặt _tip mới trong setState và chờ nó hoàn tất
  • bọc phần nội dung trong RefreshIndicator với onRefresh: refresh
  • đặt FutureBuilder trong một ListView bên trong nó

Trong bản xem trước, dùng chuột kéo màn hình xuống.

Tự làm thử

import 'package:flutter/material.dart';

import 'api.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: TipScreen(),
    );
  }
}

class TipScreen extends StatefulWidget {
  const TipScreen({super.key});

  @override
  State<TipScreen> createState() => _TipScreenState();
}

class _TipScreenState extends State<TipScreen> {
  late Future<String> _tip;

  @override
  void initState() {
    super.initState();
    _tip = fetch('/tip');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Tip of the Day'),
      ),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(24),
          child: FutureBuilder<String>(
              future: _tip,
              builder: (context, snapshot) {
                if (snapshot.hasData) {
                  return Text(
                    snapshot.data!,
                    textAlign: TextAlign.center,
                    style: const TextStyle(fontSize: 24),
                  );
                }
                return const CircularProgressIndicator();
              },
            ),
        ),
      ),
    );
  }
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Dữ liệu và mạng

Tự luyện tập: Trình biên dịch Flutter online