1. 程式人生 > >學習如何每隔一段時間定時重複執行任務

學習如何每隔一段時間定時重複執行任務

學習了定時執行任務功能。並寫了個demo學習研究下。

參考blog:

1. 通過Service和BroadcastReceiver實現

寫一個Service執行定時發廣播操作

public class AlarmService extends Service {

    @Override
public IBinder onBind(Intent intent) {
        return null;
}

    @Override
public int onStartCommand(Intent intent, int flags, int startId) {
        // 
TODO: 16/3/28 如果執行費時操作,可以新起執行緒,但是覺得執行緒太多不好 // new Thread(new Runnable() { // @Override // public void run() { // } // }).start(); Log.e("test", "這是一條測試資訊"); AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE); int minute = 1000; long
triggerAtTime = SystemClock.elapsedRealtime() + minute; Intent i = new Intent(this, AlarmReceiver.class); PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0); manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi); return super.onStartCommand(intent, flags, startId); } }
寫一個BroadcastReceiver接收廣播啟動Service
public class AlarmReceiver extends BroadcastReceiver {

    @Override
public void onReceive(Context context, Intent intent) {
        Intent i = new Intent(context, AlarmService.class);
context.startService(i);
}
}
最後在Activity中實現迴圈。
/**
 * 這個Alarm的迴圈只能給Service用
 * Activity啟動Service,Service傳送廣播,廣播接收器接收廣播並啟動Service,Service再次傳送廣播,如此重複
 */
public class AlarmActivity extends AppCompatActivity {

    @Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
setContentView(R.layout.activity_alarm);
Intent i = new Intent(this, AlarmService.class);
startService(i);
}
    
    @Override
protected void onDestroy() {
        super.onDestroy();
Intent i = new Intent(this, AlarmService.class);
stopService(i);
}
}
最後,假如需要對UI進行操作,完全可以將BroadcastReceiver寫在Activity中,來實現定時的UI操作。

一直啟動Service我不覺得是一個好的解決方案,個人不喜歡用。

2. 通過Handler和Runnable實現迴圈

/**
 * 通過handler的post方法使用runnable,在runnable中使用handler的post方法post當前runnable,如此迴圈。
 */
public class HandlerActivity extends AppCompatActivity {

    private TextView tvNumber;
    private static int number = 0;
    private Handler handler = new Handler();
    private Runnable runnable = new Runnable() {
        @Override
public void run() {
            number++;
tvNumber.setText("" + number);
//延時1秒post
handler.postDelayed(this, 1000);
}
    };
@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler);
tvNumber = (TextView) findViewById(R.id.tvNum01);
findViewById(R.id.btnStart01).setOnClickListener(new View.OnClickListener() {
            @Override
public void onClick(View view) {
                startHandleLoop();
}
        });
findViewById(R.id.btnStop01).setOnClickListener(new View.OnClickListener() {
            @Override
public void onClick(View view) {
                stopHandleLoop();
}
        });
}

    /**
     * 開始迴圈
     */
private void startHandleLoop(){
        //延時1秒post
handler.postDelayed(runnable, 1000);
}

    /**
     * 停止迴圈
     */
private void stopHandleLoop(){
        handler.removeCallbacks(runnable);
}
}
3. 通過new一個無限迴圈的執行緒,設定sleep實現迴圈
/**
 * 通過新建一個執行緒,無限迴圈,並設定sleep時間,實現每隔一秒重新整理的功能。
 */
public class SleepActivity extends AppCompatActivity {

    private static int number = 0;
    private TextView tvNumber;
    private Handler handler3 = new Handler(){
        @Override
public void handleMessage(Message msg) {
            number++;
tvNumber.setText("" + number);
            super.handleMessage(msg);
}
    };
@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sleep);
tvNumber = (TextView) findViewById(R.id.tvNum02);
findViewById(R.id.btnStart02).setOnClickListener(new View.OnClickListener() {
            @Override
public void onClick(View view) {
                new Thread(new LoopRnuable()).start();
}
        });
}

    public class LoopRnuable implements Runnable{

        @Override
public void run() {
            while (true) {
                try {
                    Thread.sleep(1000);
Message msg = new Message();
msg.what = 1;
handler3.sendMessage(msg);
} catch (InterruptedException e) {
                    e.printStackTrace();
}
            }
        }
    }
}
4. 通過Timer實現重複迴圈
/**
 * 通過Timer的schedule方法使用TimerTask,TimerTask的內容是Handler傳送訊息。
 * 為啥用Handler呢,因為UI變化只能在UI執行緒~~
 */
public class TimerActivity extends AppCompatActivity {

    private static int number = 0;
    private TextView tvNumber;
    private Timer timer;
    private TimerTask task = new TimerTask() {
        @Override
public void run() {
            //TODO 這裡可以執行定時非UI操作
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}
    };
/**
     * 處理UI操作
     */
private Handler handler = new Handler() {
        @Override
public void handleMessage(Message msg) {
            super.handleMessage(msg);
number++;
tvNumber.setText("" + number);
}
    };
@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timer);
tvNumber = (TextView) findViewById(R.id.tvNum03);
timer = new Timer();
findViewById(R.id.btnStart03).setOnClickListener(new View.OnClickListener() {
            @Override
public void onClick(View view) {
                startTimmerLoop();
}
        });
findViewById(R.id.btnStop03).setOnClickListener(new View.OnClickListener() {
            @Override
public void onClick(View view) {
                stopTimerLoop();
}
        });
}

    /**
     * TODO 當timer被stop之後再次start會報錯 timer is canceled
*/
private void startTimmerLoop() {
        timer.schedule(task, 1000, 1000);//第二個引數是等待一秒後執行schedule,第三個引數是每隔一秒重複執行一次
}

    private void stopTimerLoop() {
        timer.cancel();
}
}

大多分析都用註釋的方式寫在程式碼中了~