我在IntentService
内创建了onHandleIntent
无限循环,然后添加静态方法start,resume,pause,stop以直接在我的Activities中调用它。
场景是,在无限循环中,我正在调用回调方法,它正在创建一个新线程来执行长进程。
问题是,我担心由于无限循环而不断创建线程。我很确定有更好的方法来管理它。我在想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 除了google api,我使用的是位置api。我将创建一个android库项目并使用该api在后台获取最新位置(例如每2秒)。
在应用程序方面,只需要调用静态方法来使用它(例如start(context,callback),pause(),resume(),stop())。它有回调来获取位置。在从location对象获取所需信息后,我将创建一个新线程来调用我自己创建的回调(由应用程序端实现)。
答案 0 :(得分:2)
您可以使用AsyncTask
而不是每次都创建新主题吗? AsyncTask管理固定的线程池(或一个后台线程 - 取决于Android版本),并允许执行后台操作并在UI线程上发布结果,而无需操纵线程和/或处理程序。
但是我想知道为什么你需要在onHandleIntent
方法中创建一个无限循环?通过这样做,您可以阻止IntentService
接收更多意图。因为在IntentService中:
所有请求都在一个工作线程上处理 - 它们可以作为 只要有必要(并且不会阻止应用程序的主循环), 但一次只能处理一个请求。
我认为你想从IntentService的UI线程中执行一些长时间运行的代码。但这不需要在IntentService工作线程中创建无限循环。只需使用Context.startService(Intent)
调用将请求发送到IntentService即可。如果您希望IntentService发回一些结果或只是在UI线程中调用回调,您可以传递Messenger
(或ResultReceiver
)对象与Intent。
<强>活动强>:
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());
}
答案 1 :(得分:1)
查看ExecutorService的文档(不要与Android服务混淆)和Executors包。有一些关于如何使用线程池的例子。
答案 2 :(得分:0)
等等,为什么你需要使用所有这些回调?你不能只是让每个意图编码需要做的事情然后让你的onHandleIntent根据意图的信息执行不同的代码。这是IntentService的使用方式。
您不应该在IntentSerivce中执行任何线程处理。 IntentService应该处理所有线程代码(你应该放弃它,因为它可能已经过高度优化)。