Giảm giật lag trong ứng dụng di động: từ 60 khung hình mỗi giây đến thực tế

  • author-image

    Nguyễn Đình Cường

  • blog-tag
  • blog-comment 0 comment
  • created-date 09 Nov, 2026
blog-thumbnail

Một ứng dụng cuộn không mượt hay phản hồi chậm sẽ bị người dùng bỏ nhanh dù có nhiều tính năng. Giật lag (jank) xảy ra khi ứng dụng không kịp vẽ khung hình mới đúng hạn. Bài viết giải thích nguyên nhân và cách đo, cách sửa hiệu quả.

Ngân sách thời gian mỗi khung hình

Màn hình 60Hz làm mới 60 lần mỗi giây, nghĩa là mỗi khung hình có khoảng 16 mili giây để hoàn thành mọi công việc. Màn hình 90Hz hoặc 120Hz còn ít thời gian hơn. Nếu một khung hình mất nhiều hơn ngân sách, bạn thấy hiện tượng khựng.

Nguyên tắc số một: giữ luồng giao diện nhẹ

Luồng giao diện (UI thread hoặc main thread) vừa xử lý cảm ứng vừa vẽ màn hình. Mọi việc nặng như phân tích JSON lớn, xử lý ảnh, đọc ghi tệp lớn, mã hóa hay tính toán phức tạp nên chuyển sang luồng khác.

// Flutter: chuyển việc nặng sang isolate riêng
import 'dart:convert';
import 'package:flutter/foundation.dart';

List<dynamic> parseJson(String text) => jsonDecode(text) as List<dynamic>;

Future<List<dynamic>> loadBigList(String text) {
  return compute(parseJson, text);
}
// Kotlin: chạy việc nặng ngoài luồng chính
viewModelScope.launch {
    val result = withContext(Dispatchers.Default) {
        heavyCalculation()
    }
    _state.value = result
}

Đo trước khi tối ưu

Đừng đoán, hãy đo bằng công cụ có sẵn:

  • Flutter DevTools: xem biểu đồ hiệu năng, phát hiện khung hình chậm; luôn đo ở chế độ profile trên thiết bị thật, không phải chế độ debug.
  • Android Studio Profiler: theo dõi CPU, bộ nhớ, mạng và năng lượng.
  • Xcode Instruments: công cụ phân tích hiệu năng cho iOS.
  • React Native: dùng công cụ hiệu năng tích hợp và Flipper hoặc các công cụ gỡ lỗi tương ứng.

Hãy thử trên điện thoại cấu hình thấp, vì thiết bị mạnh che giấu nhiều vấn đề.

Các nguyên nhân phổ biến

  1. Vẽ lại quá nhiều: cây giao diện lớn bị dựng lại do state đặt quá cao. Giải pháp: tách widget hoặc component, giới hạn phạm vi cập nhật, dùng const khi có thể.
  2. Danh sách không tối ưu: dùng danh sách tải lười (ListView.builder, LazyColumn, FlatList) thay vì dựng tất cả cùng lúc.
  3. Ảnh quá lớn: tải ảnh gốc độ phân giải cao rồi thu nhỏ khi hiển thị. Hãy yêu cầu kích thước phù hợp và dùng bộ nhớ đệm ảnh.
  4. Hiệu ứng nặng: làm mờ, đổ bóng, cắt xén phức tạp tốn tài nguyên đồ họa, đặc biệt khi chồng nhiều lớp.
  5. Việc nặng trên luồng chính: như đã nêu ở trên.
  6. Rò rỉ bộ nhớ: gây thu gom rác thường xuyên và làm chậm ứng dụng.

Mẹo cho Flutter

// Dùng const để Flutter bỏ qua việc dựng lại widget bất biến
const Padding(
  padding: EdgeInsets.all(16),
  child: Text('Tiêu đề cố định'),
)

// Giới hạn vùng vẽ lại bằng RepaintBoundary cho phần hay thay đổi
RepaintBoundary(
  child: AnimatedWidgetThatChangesOften(),
)

Thời gian khởi động

Cảm nhận đầu tiên của người dùng là thời gian mở ứng dụng. Hãy trì hoãn việc khởi tạo không cần thiết, tải dữ liệu sau khi hiện màn hình đầu, và dùng màn hình khởi động nhẹ. Tránh gọi nhiều dịch vụ tuần tự ngay khi mở.

Pin và dữ liệu

Hiệu năng không chỉ là tốc độ. Hạn chế cập nhật vị trí liên tục, thăm dò máy chủ dày đặc, và đánh thức thiết bị không cần thiết. Gom nhóm yêu cầu mạng và tận dụng bộ nhớ đệm giúp tiết kiệm cả pin lẫn dữ liệu di động.

Quy trình tối ưu gợi ý

  1. Tái hiện vấn đề trên thiết bị thật, chế độ gần với bản phát hành.
  2. Dùng profiler xác định đúng điểm nghẽn.
  3. Sửa một vấn đề mỗi lần và đo lại.
  4. Thêm kiểm tra hiệu năng vào quy trình trước khi phát hành.

Kết luận

Giữ luồng chính nhẹ, vẽ lại đúng chỗ cần vẽ và luôn đo bằng công cụ trên thiết bị thật là ba thói quen mang lại hiệu quả nhất. Tối ưu sớm theo cảm tính thường tốn thời gian mà ít tác dụng.

Kiểm tra hiệu năng như một phần của quy trình

Hiệu năng dễ xuống cấp dần theo từng tính năng mới. Hãy lập một bộ kịch bản kiểm tra cố định như mở ứng dụng, cuộn danh sách dài, chuyển tab, rồi đo định kỳ trên một thiết bị cấu hình thấp làm chuẩn. Ghi lại số liệu mỗi bản phát hành để thấy xu hướng. Khi có bản nào làm chỉ số xấu đi rõ rệt, hãy xem lại các thay đổi của bản đó trước khi phát hành. Thói quen này rẻ hơn rất nhiều so với việc sửa sau khi người dùng phàn nàn.

Để học các kỹ thuật tối ưu qua dự án thực tế, bạn có thể tham khảo khóa học tại codebem.com.

author_photo
Nguyễn Đình Cường

0 comment