使用线程删除位置更新

时间:2014-12-03 10:00:58

标签: java android multithreading android-location

我有一个服务,不断轮询web服务的某些选项。这些选项基本上重启了LocationManager。使用自定义事件完成此重新启动,该事件从线程内部使用的方法触发。

这是我的自定义事件

public class OptionsChangedEvent extends EventObject {
    public OptionsChangedEvent(Object o){
        super(o);
    }
}

和自定义侦听器

public interface OptionsChangedListener extends EventListener {
    public void optionsChanged(OptionsChangedEvent evt);
}

在服务中运行并轮询新选项的线程如下

private Thread optionsThread = new Thread() {
    public void run() {
        //Looper.prepare();
        while(true) {
            String opts = getOptsFromServer();
            if(!opts.equals(currentOpts)) updateOpts(opts); //the prob is here
            //Looper.loop();
            Thread.sleep(10 * 1000) // sleep 10sec
        }
    }
}

最后,我将如何在我的跟踪器中实现监听器。

locOpts.addOptionsChangedListener(new OptionsChangedListener() {
    @Override
    public void optionsChanged(OptionsChangedEvent event) {
        Log.d("LOCATION_OPTIONS_CHANGED", "SUCCESS");
        mLocationManager.removeUpdates(mLocationListener);
        mLocationManager.requestLocationUpdates(
                provider,
                update,
                0, mLocationListener
        );
    }
});

我遇到以下错误,基本上说我需要在我的帖子中使用Looper.loopLooper.prepare

12-03 11:31:39.544  26751-26843/com.test.location E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-10370
Process: com.test.location, PID: 26751
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:200)
at android.os.Handler.<init>(Handler.java:114)
at android.location.LocationManager$ListenerTransport$1.<init>(LocationManager.java:221)
at android.location.LocationManager$ListenerTransport.<init>(LocationManager.java:221)
at android.location.LocationManager.wrapListener(LocationManager.java:844)
at android.location.LocationManager.requestLocationUpdates(LocationManager.java:857)
at android.location.LocationManager.requestLocationUpdates(LocationManager.java:454)
at com.test.location.trackers.LocationTracker$2.optionsChanged(LocationTracker.java:93)
at com.test.location.options.LocationTrackerOptions.notifyListeners(LocationTrackerOptions.java:22)
at com.test.location.options.LocationTrackerOptions.fromJSON(LocationTrackerOptions.java:34)
at com.test.location.MainService$5.run(MainService.java:219)

如果我取消注释Looper部分,该线程只能工作一次,我无法弄清楚为什么会发生这种情况。

更新

经过一番调查后,我发现需要消息队列的代码会产生这个问题。有没有人需要做这样的事情?如果可能的话,我想不要在这里改变我的设计。

private synchronized void notifyListeners(Object obj) {
    for (OptionsChangedListener listener : listeners) {
        listener.optionsChanged(new OptionsChangedEvent(obj));
    }
}

2 个答案:

答案 0 :(得分:1)

您是否尝试在回调方法 updateOpts 中更新用户界面?

Looper准备&amp;循环使用以其他方式,如果你想将任务从UI线程发送到后台线程,所以你向线程发送消息,并在线程内部处理那个消息在Handler的handlemessage事件中。

尝试直接从您的线程中避免UI调用,也可以尝试使用runOnUIThread(...) 或AsyncTasks onPost以正确回调UI线程。

答案 1 :(得分:1)

解决方案实际上非常简单。我错过了回调函数。

locOpts.addOptionsChangedListener(new OptionsChangedListener() {
    @Override
    public void optionsChanged(OptionsChangedEvent event) {
        Log.d("LOCATION_OPTIONS_CHANGED", "SUCCESS");
        mLocationManager.removeUpdates(mLocationListener);
        mLocationManager.requestLocationUpdates(
                provider,
                update,
                0, mLocationListener,
                Looper.getMainLooper() // this was the problem

        );
    }
});