java - 使用线程删除位置更新

标签 java android multithreading android-location

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

最佳答案

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

Looper以其他方式准备和循环,以防万一你想从UI线程发送任务到后台线程,所以你发送消息到线程,并在线程内部处理该消息在Handler的handlemessage事件中。

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

关于java - 使用线程删除位置更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27268645/

相关文章:

java - 从 Java Applet 调用 JavaScript 函数的最佳方式

android - 将 URL 存储在数据库中?

c# - 取消长时间操作的最佳方法是什么?

android - 当我运行 flutter 命令时找不到 PowerShell 可执行文件

multithreading - Delphi (Indy) 线程安全类

python - PyQt:将信号连接到插槽以启动后台操作

java - 在构造函数中使用参数化类型从名称实例化类

java - 在安装方法中,有什么方法可以获取与当前文件(在hdfs中)相同文件夹中的文件列表?

java - 如何在同一台Mac上处理多个版本的JDK

java - 从不同的 AsyncTask 更改 AsyncTask 中的布局