2015-01-07 2 views
0

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

// Get the initial battery level 
    IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); 
    Intent batteryStatus = this.registerReceiver(null, ifilter); 
    int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); 
    System.out.println("Initial battery level is: " + level); 
    int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1); 
    final float batteryPctTemp0 = level/(float) scale; 
    final float batteryPct0 = batteryPctTemp0 * 100; 

    int waitTime = 60000 * interval; // 1 minute is 60000 miliseconds 
    System.out.println("Wait time is " + waitTime); 
    Runnable r = new Runnable() { 
     @Override 
     public void run(){ 
      calculateHelper(batteryPct0,startButton); 
     } 
    }; 
    Handler h = new Handler(); 
    h.postDelayed(r, waitTime); 

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

Я не могу на всю жизнь понять, как это сделать! Если я поместил всю вещь в какое-то время, она будет несколько раз открывать потоки, сбивающие телефон.

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

спасибо.


Благодаря Whooper, я добавил в этот способ регулирования порядка выполнения в цикле. Однако по какой-то причине мой метод postExecute() никогда не выполняется и ничего не происходит.

private class BatteryLifeTask extends AsyncTask<Void, Void, Void> { 

    // Member variables 
    Context appContext; 
    float batteryPct0; 
    Button startButton; 

    public BatteryLifeTask(Context context, Button start) { 
     super(); 
     appContext = context; 
     startButton = start; 
    } 

    protected Void doInBackground(Void... params) { 
     // Get the initial battery level 
     IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); 
     Intent batteryStatus = appContext.registerReceiver(null, ifilter); 
     int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); 
     System.out.println("Initial battery level is: " + level); 
     int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1); 
     final float batteryPctTemp0 = level/(float) scale; 
     batteryPct0 = batteryPctTemp0 * 100; 
     return null; 
    } 

    protected void onPostExecute() { 
     int waitTime = 60000 * interval; // 1 minute is 60000 miliseconds 
     System.out.println("In postExecute. waitTime is" + waitTime); 
     Runnable r = new Runnable() { 
      @Override 
      public void run(){ 
       System.out.println("An interval has passed."); 
       calculateHelper(batteryPct0,startButton); 
       new BatteryLifeTask(appContext,startButton).execute(); 
      } 
     }; 
     Handler h = new Handler(); 
     h.postDelayed(r, waitTime); 
    } 
} 

и мой вызов метода выполнения:

// Start the task loop 
    new BatteryLifeTask(getApplicationContext(), startButton).execute(); 

Я нашел проблему:

Я забыл установить аннотацию @Override, и этот ответ: https://stackoverflow.com/a/11127996/2247192 :

"Если ваши параметры onPostExec ute (Параметр Param) не совпадает с тем, который вы определили с помощью расширений AsyncTask < ..., ..., Param>, и вы не использовали аннотацию @Override, она никогда не будет выполнена, и вы не получите предупреждение от Eclipse ".

Так что я исправил мой метод postExecute к:

 @Override 
    protected void onPostExecute(Void aVoid) { 
     super.onPostExecute(aVoid); 
     int waitTime = 60000 * interval; // 1 minute is 60000 miliseconds 
     System.out.println("In postExecute. waitTime is " + waitTime); 
     Runnable r = new Runnable() { 
      @Override 
      public void run(){ 
       System.out.println("An interval has passed."); 
       calculateHelper(batteryPct0,startButton); 
       new BatteryLifeTask(appContext,startButton).execute(); 
      } 
     }; 
     Handler h = new Handler(); 
     h.postDelayed(r, waitTime); 
    } 

Все вопросы теперь решены.

+0

Use Service - так что даже если вы закроете APP, поток продолжит работу.и если вы хотите пробудить определенную команду в течение ожидаемого времени, запускайте ее AlarmManager, AlarmManager позволяет вам запускать «код» в заданное время SET, даже если приложение закрыто. – neferpitou

ответ

1

Попробуйте использовать AsyncTask. http://developer.android.com/reference/android/os/AsyncTask.html

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

Что-то вроде этого:

private class BatteryLifeTask extends AsyncTask<Void, Void, Void> { 
     protected void doInBackground(Void... params) { 
      // Get the initial battery level 
      IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); 
      Intent batteryStatus = this.registerReceiver(null, ifilter); 
      int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); 
      System.out.println("Initial battery level is: " + level); 
      int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1); 
      final float batteryPctTemp0 = level/(float) scale; 
      final float batteryPct0 = batteryPctTemp0 * 100; 
     } 

     protected void onPostExecute() { 
      int waitTime = 60000 * interval; // 1 minute is 60000 miliseconds 
      Runnable r = new Runnable() { 
       @Override 
       public void run(){ 
        new BatteryLifeTask.execute(); 
       } 
      }; 
      Handler h = new Handler(); 
      h.postDelayed(r, waitTime); 
     } 
} 

Имейте в виду, что этот код не тестировался. Но я надеюсь, что это дает вам идею :-)

+0

Несколько слов предостережения по вышесказанному: 1) «AsyncTask» не является жизненным циклом, поэтому, если вы выйдете из «Activity», это может привести к сбою или другому странному поведению. 2) Создание нового 'Handler' в методе' doInBackground() 'скорее всего не то, что вы хотите. Когда создается 'Handler', он привязан к' Looper' потока, в котором он создан: ваш фоновый поток. Поскольку фоновый поток управляется «AsyncTask», это скорее всего не удастся, и ваш «Runnable» будет запускаться только в потоке bg. –

+0

@LarrySchiefer, так что я должен попробовать что-то еще ....? – Riptyde4

+0

@LarrySchiefer: Я согласен с тобой на 1), но не на 2). Он создает обработчик в onPostExecute, который запускается в потоке пользовательского интерфейса. – Carnal