Hướng Nghiệp Dữ Liệu

Hướng dẫn xử lý đa luồng bằng Isolate và compute() trong Flutter

Được viết bởi Admin|0 lượt xem
Hướng dẫn xử lý đa luồng bằng Isolate và compute() trong Flutter

Tóm tắt nhanh

Tìm hiểu cách sử dụng Isolate và compute() trong Flutter để xử lý các tác vụ nặng mà không làm block UI thread.

Mục lục bài viết (29)

Flutter Isolate và compute()

Flutter chạy trên single thread (Dart Isolate), nhưng bạn có thể tạo các Isolate mới để xử lý tác vụ nặng mà không làm block UI. Bài viết này sẽ hướng dẫn bạn sử dụng Isolate và compute() trong Flutter.

Vấn đề với Single Thread

UI Thread Blocking:

[object Object]

Khi chạy code trên, UI sẽ bị đơ vì tất cả chạy trên main isolate.

Isolate là gì?

Isolate là một đơn vị thực thi độc lập trong Dart:

  • ✅ Memory Isolation: Mỗi isolate có memory riêng
  • ✅ No Shared State: Không chia sẻ state, chỉ giao tiếp qua messages
  • ✅ Parallel Execution: Có thể chạy song song
  • ✅ No Locks: Không cần locks vì không có shared memory

Sử dụng compute()

compute() là cách đơn giản nhất để chạy function trong isolate mới.

Cú pháp:

[object Object]

Ví dụ cơ bản:

[object Object]

Ví dụ thực tế: Parse JSON lớn

[object Object]

Ví dụ: Xử lý ảnh

[object Object]

Sử dụng Isolate trực tiếp

Khi cần kiểm soát nhiều hơn, sử dụng Isolate.spawn():

Ví dụ cơ bản:

[object Object]

Two-way Communication:

[object Object]

Ví dụ thực tế: Background Task

1. Download và Process File:

[object Object]

2. Heavy Calculation với Progress:

[object Object]

Best Practices

1. Khi nào dùng compute():

✅ Nên dùng khi:

  • Function là pure function (không có side effects)
  • Input và output có thể serialize
  • Tác vụ nặng nhưng đơn giản
[object Object]

2. Khi nào dùng Isolate.spawn():

✅ Nên dùng khi:

  • Cần two-way communication
  • Cần giữ isolate sống lâu
  • Cần nhiều messages
[object Object]

3. Tránh Serialization Issues:

[object Object]

4. Error Handling:

[object Object]

Performance Tips

1. Batch Processing:

[object Object]

2. Reuse Isolates:

[object Object]

Khi nào thật sự cần luồng nền

Không phải việc gì nặng cũng cần chuyển sang luồng nền. Chi phí tạo và giao tiếp với một luồng nền không nhỏ, và với các tác vụ nhỏ thì việc chuyển luồng còn chậm hơn chạy trực tiếp.

Ba trường hợp đáng dùng luồng nền:

  • Phân tích dữ liệu lớn — một danh sách vài nghìn phần tử từ API, đặc biệt khi phải biến đổi phức tạp sau khi phân tích.
  • Xử lý ảnh — thay đổi kích thước, nén, lọc. Đây là việc tốn thời gian và rất phù hợp để chạy nền.
  • Tính toán nặng — mã hoá, nén dữ liệu, tính toán số học phức tạp.

Ngược lại, những việc sau không cần luồng nền: gọi API (vốn đã bất đồng bộ), đọc một tệp nhỏ, biến đổi vài chục phần tử, tính toán mà tổng thời gian dưới khoảng mười mili giây.

Cách chọn giữa các phương án

Có ba mức, chọn theo độ phức tạp tăng dần:

  • compute() — dùng cho một tác vụ duy nhất, không cần truyền đối tượng phức tạp. Đây là lựa chọn đơn giản nhất và phù hợp với phần lớn nhu cầu.
  • Tạo luồng nền ngắn hạn cho mỗi lần chạy — khi tác vụ cần truyền nhiều dữ liệu hoặc cần kiểm soát vòng đời. Chi phí tạo luồng nằm ở khoảng vài chục mili giây, nên với tác vụ chạy liên tục thì đây là điểm cần cân nhắc.
  • Giữ một luồng nền tồn tại lâu dài — phù hợp khi có tác vụ lặp lại thường xuyên, ví dụ xử lý ảnh liên tục trong ứng dụng chinh sửa ảnh. Cách này tiết kiệm chi phí tạo luồng nhưng cần tự quản lý vòng đời và dọn dẹp khi không còn dùng.

Ba lỗi thường gặp khi làm việc với luồng nền

1. Cố gắng cập nhật giao diện từ luồng nền. Widget không thể được sửa từ luồng khác. Cách đúng là luồng nền trả kết quả về, rồi luồng giao diện cập nhật.

2. Truyền đối tượng không thể chuyển giữa các luồng. Không phải mọi đối tượng đều gửi được sang luồng khác. Nếu gặp lỗi khó hiểu khi truyền dữ liệu, hãy chuyển sang dạng dữ liệu đơn giản trước khi gửi — ví dụ chuyển danh sách chuỗi thay vì danh sách đối tượng phức tạp.

3. Giữ nhiều tác vụ nền chạy song song không giới hạn. Nếu mỗi lần người dùng bấm nút lại tạo một luồng nền mới, thiết bị yếu sẽ chậm hẳn. Hãy giới hạn số tác vụ chạy đồng thời, hoặc chờ tác vụ trước xong.

Cách kiểm tra luồng nền có thật sự giúp ích

Cách kiểm tra nhanh và đáng tin: chạy ứng dụng ở chế độ đo hiệu năng trên máy thật, thực hiện thao tác gây nặng, và xem có khung hình nào vượt ngưỡng hay không. Sau đó tạm chuyển tác vụ về luồng giao diện và đo lại để so sánh.

Điều đáng chú ý: khi chuyển một tác vụ sang luồng nền, bạn không chỉ cải thiện thời gian hoàn thành mà chủ yếu là giữ cho giao diện còn phản hồi. Người dùng chấp nhận chờ thêm nửa giây nếu thanh tiến trình vẫn chạy, nhưng không chấp nhận màn hình đứng yên dù chỉ một giây.

Kết luận

Isolate và compute() giúp bạn:

  • ✅ Xử lý tác vụ nặng mà không block UI
  • ✅ Tận dụng multi-core CPU
  • ✅ Cải thiện performance
  • ✅ Trải nghiệm người dùng tốt hơn

Tóm tắt:

  1. compute(): Đơn giản, dùng cho pure functions
  2. Isolate.spawn(): Linh hoạt hơn, cho complex tasks
  3. Memory Isolation: Mỗi isolate có memory riêng
  4. Message Passing: Giao tiếp qua messages
  5. Best Practices: Chọn đúng tool cho đúng task

Sử dụng Isolate và compute() đúng cách sẽ giúp ứng dụng Flutter của bạn mượt mà và responsive hơn!


Học Flutter bài bản theo lộ trình

Nếu bạn muốn học có người sửa bài thay vì tự ghép tài liệu, Flutter Hướng Nghiệp đào tạo theo 3 cấp:

Lớp online trực tiếp qua Zoom/Google Meet, có bản ghi lại — không bắt buộc đến cơ sở.
Xem lịch khai giảng hoặc so sánh 5 cách học lập trình mobile nếu còn phân vân.