5

在我的代码中,我使用 anIntentService来收听位置更新(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是它是顺序的,所以第二个意图必须等到第一个意图完成......

我是不是误会了什么?

4

3 回答 3

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

   }
}

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

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

于 2011-07-28T22:21:19.870 回答
2

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

于 2011-07-28T23:35:25.967 回答
1

谢谢一百万,这正是我处理位置请求所需要的。感谢您的解释并让我清楚,我对所有的looper概念都不是很熟悉,现在我更好地理解了!

如果有人需要同样的东西,如果您的位置线程没有自然停止(时间结束),请不要忘记停止线程循环器,方法join(millis)是将其添加到onHandleIntent()

                if(thread.isAlive())
                {
                    thread.onThreadStop();
                    try{
                        thread.interrupt();
                    }catch (Exception e) {
                        Log.d(TAG, "Exception on interrupt: " + e.getMessage());
                    }
                }   

after 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()似乎执行正确,在指定的时间后停止线程,甚至显示最后一个日志(方法的最后一条语句),但第二个意图没有执行......你知道为什么吗?

于 2011-07-29T12:04:50.673 回答