IntentService:如何正确入队?

Pom*_*m12 5 service android android-intent intentservice

在我的代码中,我使用a IntentService来收听位置更新(GPS或网络更新),这IntentService是在收到事件时触发的,因此它是startService()从任何活动开始的.

public class AddLocationService extends IntentService implements LocationListener {
    /*My code here*/
}

    @Override
protected void onHandleIntent(Intent intent) {
    if(getOldLoc() == null) 
    { 
        //Get a new location
        this.locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, TIME_INTERVAL_GPS, 0, this);
        this.locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, TIME_INTERVAL_GPS, 0, this);
        Log.d(AddLocationService.TAG, "Network listener started");

        this.time_start_listening = System.currentTimeMillis();
        mTimerThread mTimerRunnable = new mTimerThread();
        this.timerThread = new Thread(mTimerRunnable);
        this.timerThread.start();
    }
    else    
        /*REUSE OLD LOCATION*/
}
Run Code Online (Sandbox Code Playgroud)

现在我的问题是:当两个事件开始这个IntentService并且第二个事件启动它而第一个事件仍在请求更新时,我希望第二个事件等到第一个完全完成(找到位置OR计时器线程完成).但是,无论何时IntentService第二次执行(第一个实例仍在运行),它都会打印日志并执行并行执行.

然而,我认为主要目标IntentService是它是连续的,所以第二个意图必须等到第一个完成...

我错过了什么吗?

Rob*_*Rob 3

看来您的 onHandleIntent 方法没有阻塞它正在执行的线程,因此它将快速返回并允许处理第二个意图。不仅如此,从 LocationManager 到该线程的任何回调都不太可能被处理,因为 onHandleIntent 完成时后台线程可能会被终止。

如果您确实想使用 IntentService 来管理您的意图队列,那么您将需要在其自己的线程上进行位置处理,并在等待位置回调时将 IntentService 线程加入到位置线程中。

下面是一些演示这个想法的代码:

public class TestService extends IntentService {
    private static final String TAG = "TestService";

    private Location mLocation = null;

    public TestService() {
       super(TAG);
    }

    @Override
    public void onHandleIntent(Intent intent) {
        Log.d(TAG, "onHandleIntent");

        if (mLocation == null) {
            Log.d(TAG, "launching location thread");
            LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

            LocationThread thread = new LocationThread(locationManager);
            thread.start();
            try {
                thread.join(10000);
            } catch (InterruptedException e) {
                Log.d(TAG, "timeout");
                return;
            }

            Log.d(TAG, "join finished, loc="+mLocation.toString());
        } else {
             Log.d(TAG, "using existing loc="+mLocation.toString());
        }
    }

    private class LocationThread extends Thread implements LocationListener  {
        private LocationManager locationManager = null;

        public LocationThread(LocationManager locationManager) {
            super("UploaderService-Uploader");
            this.locationManager = locationManager;
        }

        @Override
        public void run() {
            Log.d(TAG, "Thread.run");
            Looper.prepare();
           this.locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
            this.locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);

            Looper.loop();
        }

        @Override
        public void onLocationChanged(Location location) {
            // TODO Auto-generated method stub
            Log.d(TAG, "onLocationChanged("+location.toString()+")");
            mLocation = location;
            Looper.myLooper().quit();
         }

         @Override
         public void onProviderDisabled(String arg0) {
         }

         @Override
         public void onProviderEnabled(String arg0) {
         }

         @Override
         public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
         }

   }
}
Run Code Online (Sandbox Code Playgroud)

令人感兴趣的是在线程上运行消息循环的 Looper(以允许处理回调)。

考虑到使用 IntentService 执行此操作所需的工作量,可能值得研究从 Service 派生并管理您自己的意图队列。