В основном я разрабатываю rss-канал для Android, и я хочу иметь службу обновления, которая для каждого источника получает каналы в определенное время.
Представить:
Source1 - 5minutes Source2 - 10minutes Source3 - 10 минут
Я создаю дифференциальный список, чтобы использовать только один поток, который делает запросы на обновление. Структура данных такова:
Source1 (следующий сон - 5), Source2 (следующий сон - 0, Источник 3 (следующий сон 5).. и так далее..
Что я делаю, я всегда добавляю список поставщиков (который содержит идентификатор и URL-адрес), а когда sleep is! = 0, я заказываю обновление (которое использует задачу async, я передаю список поставщиков для обновления и асинтезу выполните эту работу для меня, то есть... перейдите в Интернет, проанализируйте содержимое и обновите базу данных)
но существует один рабочий поток, который спит только ради группы, набор поставщиков и отправляется в AsyncTask для обновления.
В чем проблема.. Сначала поток не спит в течение определенного времени, поток должен спать 10 минут, я сделал способ конвертировать минут в milis, то есть:
private static int MinutesToMilis(int minutes) { return minutes * 1000 * 60; }
Я использую alogcat, виджет на моем телефоне, и поток спит около 25 минут (WTF): |
Другое дело, что я проверял, что, когда телефон заряжается, сервис работает нормально...
Вот код:
worker = new Thread(new Runnable()
{
@Override
public void run()
{
Provider[] enabledProviders = feedService.getAllProvidersEnabledData();
// Build a differential list from enabledProviders
DifList<Provider> list = getListForProviders(enabledProviders);
//
// Code starts here
int sleep;
DifNode<Provider> header = list.getFirst();
sleep = header.getInitial();
LinkedList<Provider> data = new LinkedList<Provider>();
Log.d(TAG, String.format("Worker thread started @ %s", now()));
try
{
for(int idx = 0 ; true ; list.reorderFirst(), header = list.getFirst(), idx++)
{
Log.d(TAG, String.format("Iteration %s with sleep %s", idx, sleep));
if(sleep > 0) {
Log.d(TAG, String.format("Next download in %s minutes", sleep));
// Suspend worker thread for sleep time
Thread.sleep(MinutesToMilis(sleep));
Log.d(TAG, "Worker thread waked up from sleep");
}
// Add to data
data.add(header.getKey());
// Set next sleep time
sleep = header.getDifference();
if(sleep != 0)
{
Log.d(TAG, "Worker preparing for update..");
//
// If difference to next is not 0 we dump data to async task
for(Provider p : data){
Log.d(TAG, String.format("Starting update %s @ %s", p.Name, now()));
}
Provider[] arrayData = new Provider[data.size()];
data.toArray(arrayData);
data.clear();
new UpdateBundleOfFeedsTask().execute(arrayData);
}
}
}
catch(InterruptedException ex)
{
Log.d(TAG, String.format("Worker thread was interrupted @ %s", now()));
isRunning = false;
}
Log.d(TAG, String.format("Worker thread exit @ %s", now()));
}
});
Вы действительно не должны так поступать, т.е. Иметь нить, которая никогда не умирает. Я настоятельно рекомендую вам взглянуть на сигналы тревоги: http://developer.android.com/reference/android/app/AlarmManager.html
Хорошим способом было бы:
pendingIntent
для каждого клиента, хотя в вашем случае его, кажется, слишком часто, чтобы сделать это каждые 5-10 минут, чтобы читать только некоторые RSS.
setRepeating
диспетчера сигналов тревоги: developer.android.com/reference/android/app/… и его аргументыtriggerAtTime
иinterval
(я также советую вам использоватьsetInexactRepeating
вместоsetRepeating
в вашем примере).