Запрос фоновой задачи для запуска несколько раз в Android

#java #android #multithreading #android-asynctask #android-service

#java #Android #многопоточность #android-asynctask #android-сервис

Вопрос:

У меня есть длительное вычисление, которое принимает данные датчика в качестве аргументов.

После получения результата вычисления я хотел бы вызвать метод для обновления представления.

Это вычисление может занять некоторое время, поэтому я не могу запустить его внутри кода Activity при получении данных датчика, потому что поток пользовательского интерфейса зависает или замедляется.

Поскольку я хочу запускать это вычисление каждый раз, когда получаю новые данные датчика, какие варианты предлагает мне Android?

Я пробовал использовать AsyncTask. Я бы запустил AsyncTask для выполнения вычисления с новыми данными датчика, и внутри него был бы вызван метод обновления представления onPostExecute .

К сожалению, такой подход создавал проблемы с синхронизацией анимации: AsyncTask мог завершиться после следующего, и обновление представления вызывалось с устаревшей информацией, что фактически приводило к сбоям в анимации.

Я также пытался запустить ту же AsyncTask с executeOnExecutor , передав ей исполнителя с одним потоком, но это не остановило дрожание анимации.

Наконец, я попытался запустить IntentService с обратным вызовом ResultReceiver внутри MainActivity. Хотя я могу запустить ее, она запускается только один раз. Я неправильно понял, для чего предназначены IntentServices? Кажется, я не могу запустить ее несколько раз (используя метод, который создает intent с дополнительными параметрами и вызывает startService с ним).

Резюме: У меня есть медленный метод, который работает с данными датчика. Я хочу запускать ее в фоновом режиме каждый раз, когда получаю новые данные датчика, и использовать ее результат / ответ для обновления представления.

Есть предложения?

Комментарии:

1. используйте Rx java, это работает так же, как асинхронная задача, и работает намного лучше

Ответ №1:

Ваш сервис здесь…..

 public class One extends Service {
public static final long NOTIFY_INTERVAL = 10 * 1000;
private Handler handler = new Handler();
private Timer timer = null;

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

@Override
public void onCreate() 
{
    if (timer != null) 
    {
        timer.cancel();
    } else
    {
        timer = new Timer();
    }
    timer.scheduleAtFixedRate(new DisplayTime(), 0, NOTIFY_INTERVAL);
}

class DisplayTime extends TimerTask 
{

    @Override
    public void run() {
        handler.post(new Runnable() {

            @Override
            public void run() {
                recall();
                Toast.makeText(getApplicationContext(), "run", Toast.LENGTH_SHORT).show();
            }

        });
    } 
 public void recall() {

      // Write here Async Task Method......
    }
 }           
  @Override
  public void onDestroy()
  {
    super.onDestroy();
    Toast.makeText(getApplicationContext(), "des", Toast.LENGTH_SHORT).show();
  }
}
  

Комментарии:

1. Как моя активность будет взаимодействовать с этой службой? Скажем, если моя активность получает обновления данных датчика, как она может отправить их в эту службу и получить от нее ответ?

2. Привет @volcano-secret, мне удалось связаться с Activity с помощью ResultReceiver. В конечном итоге я не совсем использовал ваш подход (мне не нужна была временная задача), но подкласс Service и использование HandlerThread сработали для меня.

Ответ №2:

Хотя я не уверен, какую анимацию вы используете, в зависимости от структуры вашего приложения и кода, несколько вариантов могут заключаться в том, что вместо обновления данных в onPostExecute (), посмотрите, можете ли вы сделать это в методе обратного вызова анимации, который сообщает вам, что анимация завершена, т. Е. Вычислите ее в asynctask, но обновите свой arraylist или что вы используете в методе обратного вызова анимации . Во-вторых, если у вас есть общее представление о том, сколько времени требуется для завершения анимации, вы можете применить обработчик с таймером и попытаться сопоставить обе операции, вызвав анимацию с задержкой. Аналогичным образом вы можете использовать широковещательный приемник или интерфейс, если операция пользовательского интерфейса распространяется на действия.

Ответ №3:

вы можете реализовать onProgressUpdate() метод AsyncTask , затем в вашем doInBackground() вызове publishProgress() вы можете обновить свой пользовательский интерфейс в onProgressUpdate()