Обновление пользовательского интерфейса во время работы в фоновом режиме
у меня есть операция обновления базы данных, которая имеет действие, которое продолжает обновлять процент и работает внутри AsyncTask.
внутри doInBackground () я вызываю контроллер, который обновляет базу данных и продолжает обновлять процент активности, однако, если я нажму кнопку "Домой" или кнопку "назад", операция будет отменена. Что ты предлагаешь мне сделать?
я пытался запустить службу внутри doInBackground (), чтобы она работала в фоновом режиме, но она похоже, не работает.
мой код выглядит так:
public class UpdateDatabaseAsyncTask extends AsyncTask<Void, Integer, Integer>
{
@Override
public void onPreExecute()
{
mCustomProgressBar.startAnimation();
}
@Override
public Integer doInBackground(Void... params)
{
return mController.updateDatabase();
}
@Override
public void onPostExecute(Integer result)
{
mCustomProgressBar.stopAnimation();
// finish the activity
}
@Override
public void onProgressUpdate(Integer... value)
{
updatePercentageValue(value[0]);
}
public void callPublishProgress(Integer value)
{
publishProgress(value);
}
}
и внутри контроллера я вызываю метод callPublishProgress(value)
передача текущего процентного значения, поэтому он будет publishProgress(value)
в пользовательском интерфейсе.
я отлаживал, и я нажал кнопку home / back, и он просто перестал запускать рабочий поток.
другое решение, которое я пробовал, запускал службу для запуска в фоновом режиме независимо от того, нажимает ли пользователь кнопку home / back или нет, поэтому я думал, и Служба сделает вызов методу контроллера, который выполняет работу, и он вызовет callPublishProgress(value)
чтобы обновить процентное значение в пользовательском интерфейсе в любом случае.
однако, что происходит, код reach doInBackground()
и запустите службу, но она переходит в onPostExecute()
сразу же, он просто не дождался окончания службы(конечно!). Так что это дает NullPointerException
. Я думал сделать петлю внутри doInBackground()
С флагом, установленным в Службе, поэтому он уйдет этот цикл, пока служба не была завершена (я использовал IntentService), но он все равно не работал.
я тоже подумал об использовании таймера. Но я не знаю.
Я читал статьи, в документации о потоках и т. д. И он предлагает использовать AsyncTask
, как я и пытался сделать. Он также говорит о runOnUiThread(Runnable)
.
в любом случае мне нужно сделать операцию в фоновом режиме(возможно, используя IntentService), поэтому независимо от того, является ли пользователь нажмите кнопку "Домой", он будет продолжать работать, но он должен обновить процент в пользовательском интерфейсе, и когда пользователь покинет экран и вернется к нему, он покажет текущее процентное значение, обновленное на экране.
что является лучшим решением для моего случая?
спасибо.
3 ответов
public class MyServce extends Service{
public static final String BROADCAST_ACTION = "com.myapp";
Intent intent;
private final Handler handler = new Handler();
@Override
public void onCreate()
{
super.onCreate();
intent = new Intent(BROADCAST_ACTION);
}
@Override
public void onStart(Intent intent, int startId) {
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1000); // 1 second
}
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
DoYourWorking();
handler.postDelayed(this, 1000); // 1 seconds
}
private void DoYourWorking() {
........
........
intent.putExtra("key", progress);
sendBroadcast(intent);
}
};
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onDestroy() {
super.onDestroy();
handler.removeCallbacks(sendUpdatesToUI);
}
Теперь в вашей деятельности регистрация вещания на службу
private BroadcastReceiver brodcast = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//intent.getWhatever
// update your progress
//progressbar.setProgress
}
зарегистрировать широковещательный
registerReceiver(brodcast, new IntentFilter(MyService.BROADCAST_ACTION));
это сработало для меня. Я запустил фоновую службу в потоке, который просто извлекает значения и обновляет объект в одиночном элементе.
в контроллере представления я запускаю таймер, который продолжает обновлять представление, извлекая данные из объекта в singleton.
У меня была небольшая проблема с пониманием всего текста вашего вопроса, поэтому я не уверен, что вы пробовали это. Но это сработало. Кроме того, служба была запущена с START_STICKY
использовать IntentService (который является сервисом в собственном потоке) и проводник для передачи данных обратно в действие.