Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีรันเมธอดทุก 10 วินาทีใน Android (Handler, Coroutine, WorkManager)

ภาพรวม

บทความนี้สาธิตวิธีรันโค้ดซ้ำทุก 10 วินาทีใน Android โดยเปรียบเทียบ 3 วิธีหลัก: Handler (Legacy), Kotlin Coroutine (แนะนำ), และ WorkManager (สำหรับ Background Work) พร้อมベスト Practices การจัดการ Lifecycle

ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่

สร้างโปรเจกต์ Android ใหม่ใน Android Studio (แนะนำใช้ Kotlin)

วิธีที่ 1: Handler + Runnable (Java Legacy - โค้ดต้นฉบับ)

Layout (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Handler ทุก 10 วินาที"
        android:textSize="18sp" />

</LinearLayout>

MainActivity.java

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private Handler handler = new Handler(Looper.getMainLooper());
    private Runnable runnable;
    private final int delay = 10000; // 10 วินาที

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

    @Override
    protected void onResume() {
        super.onResume();
        startPeriodicTask();
    }

    @Override
    protected void onPause() {
        super.onPause();
        stopPeriodicTask();
    }

    private void startPeriodicTask() {
        runnable = new Runnable() {
            @Override
            public void run() {
                // ทำงานที่นี่ทุก 10 วินาที
                Toast.makeText(MainActivity.this, "รันทุก 10 วินาที (Handler)", Toast.LENGTH_SHORT).show();
                
                // Schedule ครั้งถัดไป
                handler.postDelayed(this, delay);
            }
        };
        handler.postDelayed(runnable, delay);
    }

    private void stopPeriodicTask() {
        handler.removeCallbacks(runnable);
    }
}

วิธีที่ 2: Kotlin Coroutine (แนะนำสำหรับโปรเจกต์ใหม่)

build.gradle (Module: app)

dependencies {
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3"
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.7.0"
}

MainActivity.kt

import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import android.os.Bundle
import android.widget.Toast
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // ใช้ lifecycleScope - จะ cancel อัตโนมัติเมื่อ Lifecycle ถูก Destroy
        lifecycleScope.launch {
            while (true) {
                delay(10_000) // 10 วินาที
                // ตรวจสอบว่า Activity ยัง Active อยู่
                if (isDestroyed || isFinishing) return@launch
                
                runOnUiThread {
                    Toast.makeText(this@MainActivity, "รันทุก 10 วินาที (Coroutine)", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }
}

รูปแบบ Advance: ใช้ flow และ repeatOnLifecycle

import androidx.lifecycle.repeatOnLifecycle
import androidx.lifecycle.Lifecycle.State.STARTED
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.collect

lifecycleScope.launch {
    repeatOnLifecycle(STARTED) {
        flow {
            while (true) {
                emit(Unit)
                delay(10_000)
            }
        }.collect {
            // ทำงานที่นี่ - 運行เฉพาะเมื่อ UI มองเห็น (STARTED)
            Toast.makeText(this@MainActivity, "รันทุก 10 วินาที (Flow + Lifecycle)", Toast.LENGTH_SHORT).show()
        }
    }
}

วิธีที่ 3: WorkManager (สำหรับ Background Periodic Work)

เหมาะสำหรับงานที่ต้องรันแม้แอปจะปิดอยู่ (Sync ข้อมูล, Backup, Upload Log)

build.gradle

dependencies {
    implementation "androidx.work:work-runtime-ktx:2.9.0"
}

Worker Class

import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import kotlinx.coroutines.delay

class PeriodicWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
    override suspend fun doWork(): Result = try {
        // ทำงาน Background ที่นี่
        delay(100) // จำลองงาน
        Result.success()
    } catch (e: Exception) {
        Result.failure()
    }
}

การจัดตารางงาน (Schedule)

import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import java.util.concurrent.TimeUnit

val workRequest = PeriodicWorkRequestBuilder<PeriodicWorker>(15, TimeUnit.MINUTES)
    .setInitialDelay(10, TimeUnit.SECONDS)
    .build()

WorkManager.getInstance(context).enqueueUniquePeriodicWork(
    "periodic_sync",
    ExistingPeriodicWorkPolicy.KEEP,
    workRequest
)
หมายเหตุ: WorkManager มีขั้นต่ำ 15 นาที (API 23+) ไม่สามารถตั้ง 10 วินาทีได้ ต้องใช้ Handler/Coroutine แทน

ตารางเปรียบเทียบ

คุณสมบัติHandlerCoroutine + LifecycleWorkManager
ความแม่นยำเวลาประมาณ (~10 วิ)แม่นยำมากประมาณ (≥15 นาที)
รันเมื่อแอปปิดไม่ได้ไม่ได้ได้
จัดการ LifecycleManualอัตโนมัติอัตโนมัติ
Doze Modeไม่รองรับไม่รองรับรองรับ
สำหรับ UI Updatesได้ได้ (แนะนำ)ไม่ได้

ข้อแนะนำ

  • UI Periodic Updates: ใช้ Coroutine + repeatOnLifecycle
  • Background Sync (แอปปิดได้): ใช้ WorkManager (interval ≥ 15 นาที)
  • Legacy Java Project: ใช้ Handler พร้อม removeCallbacks ใน onPause/onDestroy
  • ห้ามใช้: Thread.sleep() บน Main Thread, TimerTask (Leak เงื่อนไข)