2

我在IntentService里面创建了无限循环,onHandleIntent然后添加静态方法开始、恢复、暂停、停止以在我的活动中直接调用它。

场景是,在无限循环中,我正在调用回调方法,该方法正在创建一个新线程来执行长进程。

问题是,我担心由于无限循环而不断创建线程。我很确定有更好的方法来管理它。我正在考虑 ThreadPool 或其他能够以顺序方式仅使用一个线程的东西。因此,我节省了时间、内存、开销等。

其他方法非常受欢迎。根据需要向我询问其他信息。然后,我会在这里更新。

这是我的代码(看看 SampleCallback):

意向服务

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;
         }
     }
}

示例回调

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())。它具有获取位置的回调。从位置对象获取所需信息后,我将创建一个新线程来调用我自己创建的回调(由应用程序端实现)。

4

3 回答 3

2

您可以使用AsyncTask而不是每次都创建一个新线程吗?AsyncTask 管理一个固定的线程池(或一个后台线程 - 取决于 Android 版本)并允许执行后台操作并在 UI 线程上发布结果,而无需操作线程和/或处理程序。

但是我想知道为什么你需要在onHandleIntent方法中创建一个无限循环?通过这样做,您可以防止您IntentService收到更多的意图。从 IntentService 开始:

所有请求都在单个工作线程上处理——它们可能需要尽可能长的时间(并且不会阻塞应用程序的主循环),但一次只会处理一个请求。

我认为您想从 IntentService 的 UI 线程中执行一些长时间运行的代码。但这不需要在 IntentService 工作线程中创建无限循环。只需根据需要使用调用将请求发送到 IntentService Context.startService(Intent)。如果您希望 IntentService 发回一些结果或只是在 UI 线程中调用回调,您可以使用 Intent传递一个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);
}

意向服务

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()); 
}
于 2011-10-14T11:29:12.393 回答
1

查看ExecutorService的文档(不要与 Android 服务混淆)和Executors包。那里有一些关于如何使用线程池的示例。

于 2011-10-06T02:42:16.593 回答
0

So wait, why do you need to use all these callbacks? Can't you just have each intent encode what needs to be done and then have your onHandleIntent execute different code based on the information of the intent. This is the way IntentService is intended to be used.

You shouldn't be doing any of the thread handling in the IntentSerivce. The IntentService is supposed to be handling all the threading code (and you should let it because it's probably highly optimized).

于 2011-10-18T20:07:02.077 回答