我有一个服务,不断轮询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.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));
}
}
答案 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
);
}
});