Android IntentService:如何正确排队?

Android IntentService:如何正确排队?,android,service,android-intent,intentservice,Android,Service,Android Intent,Intentservice,在我的代码中,我使用一个IntentService来监听位置更新(GPS或网络更新),这个IntentService是在接收到事件时触发的,因此它从任何活动中以startService()启动 public class AddLocationService extends IntentService implements LocationListener { /*My code here*/ } @Override protected void onHandleIntent(I

在我的代码中,我使用一个
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*/
}
现在我的问题是:当两个事件启动此
IntentService
时,第二个事件启动它,而第一个事件仍在请求更新,我希望第二个事件等待第一个事件完全完成(找到位置或计时器线程完成)。 但是,每当第二次执行
IntentService
时(第一个实例仍在运行),它就会打印日志,并按照并行执行的方式执行

然而,我认为,
IntentService
的主要目标是它是一个连续的东西,所以第二个意图必须等到第一个意图完成后才能实现


我是否理解错了什么?

您的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) {
         }

   }
}
有趣的是,有一个循环器在线程上运行消息循环(以允许处理回调)


考虑到使用IntentService执行此操作所需的努力,可能值得研究从服务派生并管理您自己的intent队列。

OnHandleContent已经在它自己的线程中。你不(不应该)在那里创造。这一切都由IntentService为您处理

非常感谢,这正是我处理定位请求所需要的。 谢谢你的解释,让我明白,我不是很熟悉所有的活套概念,现在我更了解它

如果有人需要同样的东西,如果您的位置线程没有自然停止(在
join(millis)
上的时间结束),请将其添加到
onHandleIntent()

thread.join(yourTime)
之后,例如,如果您没有找到任何位置更新,您仍然会在特定时间后停止线程。在方法
onThreadStop()
上:

                /*We remove location updates here and stop the looper*/
                public void onThreadStop()
                {
                    this.locationManager1.removeUpdates(this);
                    handleLocationChange(AddLocationService.this.currentBestLocation);
                    Looper.myLooper().quit();
                }
然而,我认为我在第一次运行此代码时看到我的两个意图被处理,但是现在只有第一个意图被处理,当我有多个意图时,仍然请求位置更新。 我的方法
onHandleIntent()
似乎执行正确,在指定的时间后停止线程,甚至显示最后一个日志(方法的最后一条语句),但第二个意图没有执行。。。
你知道为什么吗?

Hey@Rob,谢谢你的回复。当你说
onHandleIntent
方法没有阻塞线程时,你能更具体一点吗?我该怎么做才能阻止它?这与从另一个活动创建意图时的标志有关,还是我应该在
onHandleIntent()
方法中执行?编辑:我想我理解你的意思:我的IntentService在仍然请求更新时返回。我怎样才能把它封锁起来。duo
wait()-notify()
是个好主意吗?我已经更新了我的答案,提供了更多关于如何修复它的信息。也可以直接在IntentService后台线程上使用循环器,但我有点紧张,我不确定这是否会对IntentService管理队列的任何操作产生负面影响。经过几次测试后,我注意到只有在某些情况下(当我调用
thread.interrupt()
,即当时间到期时),线程仍然在最后运行,这可能就是为什么下一个意图没有得到处理。但是,当线程正常完成时,线程会完全停止(
thread.isAlive()
返回false),并发送我的下一个意图。因此,我的问题是:如何正确地停止我的线程,和/或为什么在使用
thread.interrupt()
时它没有停止??
                /*We remove location updates here and stop the looper*/
                public void onThreadStop()
                {
                    this.locationManager1.removeUpdates(this);
                    handleLocationChange(AddLocationService.this.currentBestLocation);
                    Looper.myLooper().quit();
                }