Я хочу начать новый поток в моей собственной службе, которая запускается из операции. В этой теме я хочу обновлять данные в базе данных каждые 3 секунды. Я создал базу данных и инициализировал ее в моем методе onStartCommand (). Где мне реализовать свою тему и как?

Я пробовал это, но это не сработало, приложение, к сожалению, будет закрыто. Без вызова этого метода все работает фин.

Я создаю этот метод, который я вызвал в своем onStartCommand

private void startThreadUpdatingDatabase(){
    Log.d("Database", "startThreadUpdatingDatabase(was called)");
    new Thread(new Runnable() { 
        public void run(){
            //do stuff
        }
    }).start();
}
1
d4rty 3 Дек 2014 в 01:47

2 ответа

Лучший ответ

Если вы хотите запустить повторяющуюся задачу, вы можете попробовать разные подходы:

1) Будильник
2) Хендлер
3) TimerTask (наименее любимый)

Будильник :

private AlarmManager mAlarmManager;
private static final long ALARM_INTERVAL = 3 * 60 * 1000;

private void issueAlarm() {
    if(mAlarmManager == null)
        mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    Calendar calendar = Calendar.getInstance(Locale.US);
    calendar.add(Calendar.MILLISECOND, (int) ALARM_INTERVAL);
    Intent intent = new Intent(this, AlarmBroadcastReceiver.class);
    alarmIntent = PendingIntent.getBroadcast(this, ALARM_REQUEST_CODE, intent, 0);
    mAlarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), ALARM_INTERVAL, alarmIntent);
}

Создайте свой AlarmReceiver:

public class AlarmBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //Do DB Stuff here
    }

}

И не забудьте прописать в манифесте:

<receiver
    android:name=".AlarmBroadcastReceiver"
    android:exported="false" />

Обработчик :

@Override
public void onCreate() {
    // Start up the thread running the service.  Note that we create a
    // separate thread because the service normally runs in the process's
    // main thread, which we don't want to block.  We also make it
    // background priority so CPU-intensive work will not disrupt our UI.
    HandlerThread thread = new HandlerThread("ServiceStartArguments",
        Process.THREAD_PRIORITY_BACKGROUND);
    thread.start();

    // Get the HandlerThread's Looper and use it for our Handler
    mServiceLooper = thread.getLooper();
    mServiceHandler = new ServiceHandler(mServiceLooper);
}

И поставьте свою опубликованную задачу в очередь

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    //As danny117 pointed out, multiple clients starting the service
    //Can trigger this.
    mServiceHandler.removeCallbacks(yourRunnable);
    mServiceHandler.post(yourRunnable);
    return super.onStartCommand(intent, flags, startId);
}

Runnable должен выглядеть так:

private Runnable yourRunnable = new Runnable() {
        @Override
        public void run(){
        //DB work here
        if(mServiceHandler != null)
            mServiceHandler.postDelayed(this, ALARM_INTERVAL);
        }
}

Также убирайте после остановки обслуживания:

@Override
public void onDestroy() {
    super.onDestroy();
    mServiceHandler.removeCallbacks(yourRunnable);
    mServiceLooper.quit();
}

Таймер :

Создайте свой таймер:

private Timer myTimer = new Timer();

Создайте повторяющуюся задачу таймера:

private void scheduleTask() {
    myTimer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            //Do DB stuff here
        }
    }, 0, ALARM_INTERVAL);
}

Рекомендации:
Планирование повторяющихся сигналов тревоги
Создание службы

2
Toguard 3 Дек 2014 в 19:24

Чтобы повторить с задержкой, вы создаете runnable, который вызывает postDelayed обработчика, чтобы перезапустить его по истечении заданного периода времени.

//change the notificationSmallIcon (titlebar) so it flashes every few seconds
private static Runnable iconWarnRunnable = new Runnable() {
    @Override
    public void run() {
        if (isWarningRunning) {
            long dely;
            if (notificationSmallIcon == R.drawable.ic_launcher2) {
                notificationSmallIcon = R.drawable.ic_launcher2x;
                dely = iconWarnDelay1;
            } else {
                notificationSmallIcon = R.drawable.ic_launcher2;
                dely = iconWarnDelay2;
            }
            notifyHandler.postDelayed(this, dely);
            myShowNotification();
        } else {
            //just in nick of time
            notificationSmallIcon = R.drawable.ic_launcher2;
        }
    }
};

final HandlerThread myThread = new HandlerThread("myHandlerThread");
private static long iconWarnDelay1;
private static long iconWarnDelay2;


@Override
public void onCreate() {
    iconWarnDelay1 = 2500;
    iconWarnDelay2 = 500;
    myThread.start();
    myThread.setPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
    notifyHandler = new Handler(myThread.getLooper());

... там, где вы запускаете runnable, очень важно, чтобы при запуске вы сначала удалили, чтобы у вас всегда был только один запуск.

isWarningRunning = true;
notifyHandler.removeCallbacks(iconWarnRunnable);
notifyHandler.postDelayed(iconWarnRunnable, iconWarnDelay1);

... где-нибудь остановите работающий

isWarningRunning = false;
notifyHandler.removeCallbacks(iconWarnRunnable);
0
danny117 3 Дек 2014 в 02:49