2011-10-06 34 views
2

我創建IntentService具有無限循環內的onHandleIntent然後添加靜態方法啓動,恢復,暫停內妥善處理順序線程,停下來直接稱它爲我的活動範圍內。安卓:如何無限循環

這種情況是,在無限循環內,我調用正在創建一個新線程來執行長進程的回調方法。

問題是,我擔心由於無限循環而不斷創建線程。我很確定有更好的方法來管理它。我正在考慮ThreadPool,或者只能以順序方式使用一個線程的東西。所以,我節省了時間,內存,開銷等。

其他方法非常好。根據需要向我詢問其他信息。然後,我會在這裏更新。

這裏是我的代碼(看看SampleCallback):

IntentService

import android.app.IntentService; 
import android.content.Intent; 
import android.os.Handler; 
import android.os.Message; 
import android.util.Log; 

public class SampleCallbackIntentService extends IntentService { 
    private final String LOG_LOGCAT_TAG = "SampleCallbackIntentService"; 
    private Handler _handler; 

    public SampleCallbackIntentService(String name) { 
     super(name); 
    } 

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

     // initialize variables for pause & resume thread 
     _mPauseLock = new Object(); 
     _mPaused = false; 
     _mFinished = false; 

     // initialize handler to switch to UI/Main thread 
     _handler = new Handler() 
      { 
       @Override 
       public void handleMessage(final Message msg) 
       { 
        _callback.doSomethingFromUIThread(msg); 
       } 
      }; 
    } 

    private final SampleCallback _callback = new SampleCallback() { 
     @Override 
     public void doSomethingFromCurrentThread(final Object object) { 
      new Thread(new Runnable() { 
       @Override 
       public void run() { 
        //do long running process. 
            // I will access object here. 
       } 
      }).start(); 

     } 

     @Override 
     public void doSomethingFromUIThread(final Message msg) { 
      //may update UI here. 
     } 
    }; 

    private final int CALLBACK_MESSAGE = 1; 
    @Override 
    protected void onHandleIntent(Intent arg0) { 
     Log.i(LOG_LOGCAT_TAG, "loop started"); 
     while (!_mFinished) { 
      // do stuff here 
      // create the object variable. Then pass to callback method 
      _callback.doSomethingFromCurrentThread(object); 

      // process and create the result to pass 
      String someResult = "some result here"; 
      _handler.sendMessage(_handler.obtainMessage(CALLBACK_MESSAGE, someResult)); 

      synchronized (_mPauseLock) { 
       while (_mPaused) { 
        try { 
         Log.i(LOG_LOGCAT_TAG, "loop paused"); 
         _mPauseLock.wait(); 
         Log.i(LOG_LOGCAT_TAG, "loop resumed"); 
        } catch (InterruptedException e) { 
         Log.e(LOG_LOGCAT_TAG, "error occured on pause", e); 
        } 
       } 
      } 
      try { 
       //using sleep here might be not good design. 
       Thread.sleep(1000); 
      } catch (InterruptedException e) { 
       Log.e(LOG_LOGCAT_TAG, "error occured on sleep", e); 
      } 
     } 
     Log.i(LOG_LOGCAT_TAG, "loop ended"); 
    } 

    private static Object _mPauseLock; 
    private static boolean _mPaused; 
    private static boolean _mFinished; 

    public static void start(Context context) { 
     Intent service = new Intent(context, SampleCallbackIntentService .class); 
     if(context.startService(service)==null) { 
      Log.e(LOG_LOGCAT_TAG, "Service cannot be started"); 
     } else { 
      Log.i(LOG_LOGCAT_TAG, "start() called"); 
     } 

    } 

    /** 
    * Call this on pause. 
    */ 
    public static void pause() { 
     Log.i(LOG_LOGCAT_TAG, "pause() called"); 
     synchronized (_mPauseLock) { 
      _mPaused = true; 
     } 
    } 

    /** 
    * Call this on resume. 
    */ 
    public static void resume() { 
     Log.i(LOG_LOGCAT_TAG, "resume() called"); 
     synchronized (_mPauseLock) { 
      _mPaused = false; 
      _mPauseLock.notifyAll(); 
     } 
    } 

    public static void stop() { 
     if(_mPauseLock == null) return; 
     synchronized (_mPauseLock) { 
      Log.i(LOG_LOGCAT_TAG, "stop() called"); 
      _mFinished = true; 
     } 
    } 
} 

SampleCallback

import android.os.Message; 

public interface SampleCallback { 

    public void doSomethingFromCurrentThread(final Object object); 

    public void doSomethingFromUIThread(final Message msg); 
} 

UPDATES1 我使用的位置API一邊F rom google api。我將創建一個android庫項目,並使用該api獲取後臺中的最新位置(例如每2秒)。

在應用程序方面,只需要調用靜態方法來使用它(例如啓動(背景下,回調),暫停(),恢復(),停止())。它有回調來獲取位置。從位置對象獲取所需信息後,我將創建一個新線程來調用我自己創建的回調(由應用程序端實現)。

+0

這樣做甚至可以嗎?在'stop()'你正在使用非靜態成員'_mPauseLock'。這甚至有可能嗎? –

+0

@Sherif哦謝謝你指出。將其視爲已編譯的源代碼。我會將其改爲靜態。 – eros

+0

我添加了關於我想實現的信息。 – eros

回答

1

看看能否ExecutorService的文檔(不與Android服務混淆)和Executors包。關於如何使用線程池,有幾個例子。

+0

老實說,我不確定推薦ThreadPool。這可能是在我上面的例子中使用ExecutorService/Executors的幫助?如果是,那怎麼可能? – eros

2

您可以使用AsyncTask而不是每次創建一個新線程? AsyncTask管理一個固定的線程池(或一個後臺線程 - 取決於Android版本),並允許執行後臺操作並在UI線程上發佈結果,而無需操作線程和/或處理程序。

但是我不知道爲什麼你需要創建onHandleIntent方法內的無限循環?通過這樣做,您可以防止IntentService接收更多意圖。由於IntentService:

的所有請求都在一個工作線程處理 - 他們可能會採取只要有必要 (並不會阻止該應用程序的主循環), 但只有一個請求,將在處理時間。

我想你想在IntentService的UI線程中執行一些長時間運行的代碼。但是這並不需要在IntentService工作線程中創建一個無限循環。只需使用Context.startService(Intent)呼叫將請求發送到IntentService。如果您希望IntentService發送一些結果或僅在UI線程中調用回調,則可以將Messenger(或ResultReceiver)對象與意圖一起傳遞。

活動

final Handler uiHandler = new Handler(Looper.getMainLooper()); 

private void postTask() { 
    Intent intent = new Intent("com.yourservice.DOACTION"); 
    intent.putExtra("messenger", new Messenger(handler)); 
    intent.putExtra("object", YourObject()); // pass other Parcelable objects 
    startService(intent); 
} 

IntentService

protected void onHandleIntent(Intent intent) { 
    Messenger messenger = intent.getParcelableExtra("messenger"); 
    YourObject object = intent.getParcelableExtra("object"); 

    //... do work here ... 

    Message msg = Message.obtain(); 
    msg.what = CALLBACK_MESSAGE; 
    msg.setData(someResult); 
    messenger.send(Message.obtain()); 
} 
+0

「在這裏工作」 - >這是一個無限循環? – eros

+0

或只是一個過程,然後創建一個無限循環來調用startService? – eros

+0

我懷疑你完全需要無限循環。你會做什麼?從傳感器獲取信息或等待另一條消息?但它不適合這些任務。如果你想在後臺執行一些任務,並通知用戶使用普通服務而不是IntentService - 只需從「Service.onStartCommand」開始「AsyncTask」,並在AsyncTask完成時調用「messenger.send」。 – Idolon

0

所以等待,爲什麼你需要使用所有這些回調?難道你不能只是每個意圖都需要編碼什麼,然後讓onHandleIntent根據意圖信息執行不同的代碼。這是意圖使用IntentService的方式。

您不應該在IntentSerivce中進行任何線程處理。 IntentService應該是處理所有的線程代碼(你應該讓它,因爲它可能高度優化)。

+0

我已更新我的帖子 – eros

+0

我仍然不相信你需要做所有這些體操才能適應你的回調。我覺得你可以更簡單地使用處理程序來實現這一點,並且只需一個簡單的IntentService。 –