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