【问题标题】:Removing location updates using a thread使用线程删除位置更新
【发布时间】:2014-12-03 10:00:57
【问题描述】:

我有一项服务会不断轮询网络服务以获取某些选项。这些选项基本上会重新启动 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));
    }
}

【问题讨论】:

    标签: java android multithreading android-location


    【解决方案1】:

    您是否尝试在回调方法 updateOpts 中更新 UI?

    循环器准备和循环以其他方式使用,以防当您想将任务从 UI 线程发送到后台线程时,您将消息发送到线程,并在线程内部在 Handler 的 handlemessage 事件中处理该消息。

    尽量避免直接从您的线程调用 UI,也可以尝试使用 runOnUIThread(...) 或 AsyncTasks onPost 对 UI 线程进行适当的回调。

    【讨论】:

    • 我不是要更新用户界面。我只是触发了一个停止位置更新的事件。然后它只是再次开始位置更新。我和ui无关。
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2018-09-13
      • 2015-07-29
      • 1970-01-01
      • 2016-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多