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

Cập nhật UI từ IntentService trong Android bằng BroadcastReceiver

Tổng quan về IntentService

IntentService là Service chạy nền (background) xử lý tác vụ bất đồng bộ trên worker thread riêng. Nó tự động dừng sau khi xong việc (khác với Service thường cần stopSelf()).

Vấn đề: IntentService không thể cập nhật UI trực tiếp (chạy trên background thread). Cần cơ chế truyền dữ liệu về Main Thread.

Giải pháp: LocalBroadcastManager

Sử dụng LocalBroadcastManager (hoặc BroadcastReceiver hệ thống) để gửi Intent từ Service → Activity.

Các bước thực hiện

Bước 1: Tạo dự án mới

Android Studio → File → New Project → Empty Activity.

Bước 2: Layout (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/tvResult"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Nhấn để bắt đầu Service"
        android:textSize="22sp"
        android:padding="24dp"
        android:background="?attr/selectableItemBackground"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Bước 3: Tạo MyIntentService.java

package com.example.intentserviceuiupdate;

import android.app.IntentService;
import android.content.Intent;
import android.os.IBinder;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

public class MyIntentService extends IntentService {

    public static final String ACTION_UPDATE_UI = "com.example.intentserviceuiupdate.UPDATE_UI";
    public static final String EXTRA_DATA = "extra_data";

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null; // IntentService không hỗ trợ binding
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        // Giả lập tác vụ nặng (network, DB, compute...)
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        // Gửi broadcast local về Activity
        Intent broadcastIntent = new Intent(ACTION_UPDATE_UI);
        broadcastIntent.putExtra(EXTRA_DATA, "✅ Dữ liệu từ IntentService: Tutorialspoint.com");
        LocalBroadcastManager.getInstance(this).sendBroadcast(broadcastIntent);
    }
}

Bước 4: MainActivity.java với BroadcastReceiver

package com.example.intentserviceuiupdate;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

public class MainActivity extends AppCompatActivity {

    private TextView tvResult;
    private BroadcastReceiver uiUpdateReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvResult = findViewById(R.id.tvResult);
        tvResult.setOnClickListener(v -> startService(new Intent(this, MyIntentService.class)));

        // Khởi tạo receiver
        uiUpdateReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String data = intent.getStringExtra(MyIntentService.EXTRA_DATA);
                tvResult.setText(data);
            }
        };
    }

    @Override
    protected void onStart() {
        super.onStart();
        // Đăng ký receiver khi Activity visible
        LocalBroadcastManager.getInstance(this)
            .registerReceiver(uiUpdateReceiver, new IntentFilter(MyIntentService.ACTION_UPDATE_UI));
    }

    @Override
    protected void onStop() {
        super.onStop();
        // Hủy đăng ký tránh memory leak
        LocalBroadcastManager.getInstance(this).unregisterReceiver(uiUpdateReceiver);
    }
}

Bước 5: Khai báo Service trong AndroidManifest.xml

<application ...>
    <activity android:name=".MainActivity" ...>...</activity>
    <service android:name=".MyIntentService" />
</application>

Luồng hoạt động

  1. User click TextView → startService() khởi động MyIntentService
  2. Service chạy onHandleIntent() trên background thread
  3. Xong việc → gửi broadcast local với dữ liệu kết quả
  4. Activity nhận broadcast trong onReceive() (chạy trên Main Thread) → cập nhật UI

Kết quả

Click "Nhấn để bắt đầu Service" → chờ 2 giây → TextView cập nhật "✅ Dữ liệu từ IntentService: Tutorialspoint.com".

Cập nhật UI từ IntentService trong Android bằng BroadcastReceiver

Lưu ý hiện đại

IntentService đã deprecated từ API 30 (Android 11). Nên dùng:

  • WorkManager - cho tác vụ nền có điều kiện, đảm bảo thực thi
  • Coroutines + Flow (Kotlin) - cho async đơn giản
  • Foreground Service - cho tác vụ dài, cần thông báo