Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách làm cho Intent thông báo resume thay vì tạo mới

Giới thiệu

Bài tập trung vào việc cấu hình PendingIntent và Intent flags để đảm bảo bấm thông báo **resume (tiếp tục)** Activity hiện có thay vì tạo instance mới.

So sánh các phương pháp

Phương phápKết quả
Không set flagTạo Activity mới mỗi lần bấm (nhiều instance trong stack)
FLAG_ACTIVITY_CLEAR_TOPXóa các Activity trên đỉnh, nhưng vẫn tạo mới nếu chưa có
FLAG_ACTIVITY_SINGLE_TOPKhông tạo mới nếu đang ở đỉnh, nhưng không xóa các Activity khác
CLEAR_TOP + SINGLE_TOP (Khuyên dùng)Resume instance hiện có, xóa stack phía trên, gọi onNewIntent()
android:launchMode="singleTop" (Manifest)Tương tự SINGLE_TOP, nhưng áp dụng toàn cục
android:launchMode="singleTask"Chỉ 1 instance per task, xóa stack phía trên, nhưng có thể thay đổi task root

Code chuẩn (Best Practice)

1. Intent flags

Intent intent = new Intent(context, TargetActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
// Thêm data phân biệt
intent.putExtra("source", "notification");
intent.putExtra("data_id", itemId);

2. PendingIntent flags

PendingIntent pendingIntent = PendingIntent.getActivity(
        context,
        requestCode,           // Dùng requestCode khác nhau cho các action khác nhau
        intent,
        PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT
);
FLAG_UPDATE_CURRENT: Cập nhật extra data trong intent nếu PendingIntent đã tồn tại. Rất quan trọng khi gửi nhiều thông báo cùng target nhưng data khác nhau.

3. Xử lý trong Activity đích

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    // Luôn setIntent mới để getIntent() trả về data mới
    setIntent(intent); 
    
    if ("notification".equals(intent.getStringExtra("source"))) {
        int itemId = intent.getIntExtra("data_id", -1);
        // Load data, cập nhật UI
        loadItemDetail(itemId);
    }
}

@Override
protected void onResume() {
    super.onResume();
    // Xử lý chung cho cả cold start và resume
    handleIntent(getIntent());
}

private void handleIntent(Intent intent) {
    if (intent != null && "notification".equals(intent.getStringExtra("source"))) {
        int itemId = intent.getIntExtra("data_id", -1);
        if (itemId != -1) loadItemDetail(itemId);
    }
}

Các lỗi thường gặp

  • Quên FLAG_UPDATE_CURRENT: Tất cả thông báo mang data của cái đầu tiên.
  • Dùng requestCode = 0 cho mọi thứ: Các action khác nhau (mở chat, mở profile) ghi đè nhau.
  • Không gọi setIntent() trong onNewIntent: getIntent() vẫn trả về intent cũ.
  • Dùng FLAG_MUTABLE không cần thiết: Rủi ro bảo mật từ API 31.

Kiểm thử

  1. Mở app → điều hướng A → B → C.
  2. Gửi thông báo trỏ về C.
  3. Bấm thông báo → C hiển thị, A&B bị xóa, onNewIntent() được gọi.
  4. Bấm Back → về Home (không về B).