2011-10-06 65 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。 –