0

В моем фрагменте есть кнопка, которая при нажатии запускает сервис, который опросает датчики, и использует службу-исполнитель для хранения данных датчика в базе данных. onClick фрагмента выглядит следующим образом:Откроется диалоговое окно закрытия Android от службы

public void onClick(View v) { 
     if (!recordingStarted){ 
      try{ 
       recordingStarted = true; 
       mainActivity.startService(new Intent(mainActivity, SensorService.class)); 
       startButton.setText(getResources().getString(R.string.start_button_label_stop)); 
       Snackbar.make(coordinatorLayout, "Recording...", Snackbar.LENGTH_SHORT).show(); 
      } catch (SQLException e){ 
       mainActivity.logger.e(getActivity(),TAG, "SQL error insertSubject()", e); 
      } 
     } else { 
      dialog = new ProgressDialog(mainActivity); 
      dialog.setTitle("Stop recording"); 
      dialog.setMessage("Please wait..."); 
      dialog.show(); 

      mainActivity.stopService(new Intent(mainActivity, SensorService.class)); 
      startButton.setEnabled(false); 
      Snackbar.make(coordinatorLayout, "Recording stopped.", Snackbar.LENGTH_SHORT).show(); 
     } 
    } 

SensorService класс создан для хранения данных датчиков в базу данных каждые 10 мс с использованием ExecutorService.

Соответствующие части этого класса являются:

public class SensorService extends Service implements SensorEventListener { 

    public void onSensorChanged(SensorEvent event) { 
      //get sensor values here 

      //insert into database 
      try{ 
       executor.execute(insertHandler); 
      } catch (SQLException e) { 
       Log.e(TAG, "insertData: " + e.getMessage(), e); 
      } 
     } 
    } 

    @Override 
    public void onCreate() { 
     super.onCreate(); 

     dbHelper = new DBHelper(getApplicationContext()); 

     PowerManager manager = 
       (PowerManager) getSystemService(Context.POWER_SERVICE); 
     wakeLock = manager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); 

     registerReceiver(receiver, new IntentFilter(Intent.ACTION_SCREEN_OFF)); 

     //Executor service and runnable for DB inserts 
     executor = Executors.newSingleThreadExecutor(); 
     insertHandler = new InsertHandler(); 
    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     super.onStartCommand(intent, flags, startId); 

     startForeground(Process.myPid(), new Notification()); 
     registerListener(); 
     wakeLock.acquire(); 

     return START_STICKY; 
    } 

    @Override 
    public void onDestroy() { 
     //Prevent new tasks from being added to thread 
     executor.shutdown(); 

     try { 
      //Wait for all tasks to finish before we proceed 
      while (!executor.awaitTermination(10, TimeUnit.SECONDS)) { 
       Log.i(TAG, "Waiting for current tasks to finish"); 
      } 
     } catch (InterruptedException e) { 
      executor.shutdownNow(); 
     } 

     //Stop everything else once the task queue is clear 
     unregisterReceiver(receiver); 
     unregisterListener(); 
     wakeLock.release(); 
     dbHelper.close(); 
     stopForeground(true); 
    } 

    class InsertHandler implements Runnable { 
     public void run() { 
      dbHelper.insertData(Short.parseShort(MainActivity.subInfo.get("subNum")), System.currentTimeMillis(), 
        accelerometerMatrix[0], accelerometerMatrix[1], accelerometerMatrix[2], 
        accelerometerWorldMatrix[0], accelerometerWorldMatrix[1], accelerometerWorldMatrix[2], 
        gyroscopeMatrix[0], gyroscopeMatrix[1], gyroscopeMatrix[2]); 
     } 
    } 
} 

Так что, когда попадает пользователь кнопка SensorService проходит через его onCreate и onStartCommand методами. Всякий раз, когда данные датчика меняются, служба-исполнитель вставляет его в базу данных

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

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

Таким образом, я показываю прогрессдиалог в самом фрагменте, когда нажата кнопка остановки. Но как я могу отменить диалог только после того, как служба-исполнитель закончила обработку очереди и закрыта правильно?

я могу легко сделать это с асинхронными задачами, но я решил использовать исполнителю услуги для этого вместо того, чтобы, так что это не вариант

диалог

прогресс принадлежит к фрагменту, так что я не могу сделать что-то вроде MainActivity.dialog.dismiss() от внутри службы. Я не чувствую, что это очень чистый способ обработки вещей в любом случае

Так что, я думаю, я остался с обработчиками, но не совсем уверен, как его настроить в этом случае, потому что служба-исполнитель работает в другой службе (SensorService). Как выглядел бы код, если бы использовал обработчик для решения этой проблемы?

ответ

0

Для передачи сигнала компоненту активности необходим какой-либо механизм. Самый простой и наиболее распространенный способ сделать это - использовать шину событий. Правильная реализация этого полностью зависит от вас, но вы можете использовать существующие библиотеки маршрутизации событий, чтобы помочь вам. Вы можете найти их с помощью простого поиска в Google.