我有一个服务,它会监听位置更改并将消息与Polylineoptions一起发送到UI线程,它是这样的:
//some code here
Bundle bundle = new Bundle();
bundle.putParcelable("polylineOptions", mPolylineOptions);
Message msg = Message.obtain(null, LOCATION_UPDATE);
msg.setData(bundle);
mMainHandler.dispatchMessage(msg);
//some more code
mPolylineOptions包含新位置以及之前的所有位置。 在主线程中我有handleMessage方法,应该更新我的地图。它是这样的:
private class MainHandler extends Handler {
private MainHandler (Looper looper){
super(looper);
}
@Override
public void handleMessage (Message msg){
switch (msg.what){
case TrackingService.LOCATION_UPDATE:
if (D){Log.d(TAG, "Location update received");};
myPolylineOptions = (PolylineOptions) msg.getData().getParcelable("polylineOptions");
new Color();
myPolyline = mMap.addPolyline(myPolylineOptions
.color(Color.argb(128, 255, 0, 0))
.geodesic(true));
break;
}
}
}
我可以看到处理程序收到消息,但是当我调用
时,我得到“illegalstateexception:Not On the Main Thread” myPolyline = mMap.addPolyline(myPolylineOptions
.color(Color.argb(128, 255, 0, 0))
.geodesic(true));
有人有想法如何解决这个问题? 谢谢!
编辑:
我必须服务并向我传递我的UI处理程序,如下所示:
private ServiceConnection mConnection = new ServiceConnection() {
// Called when the connection with the service is established
public void onServiceConnected(ComponentName className, IBinder service) {
if (D) {Log.d(TAG, "main - onServiceConnected started");};
// Because we have bound to an explicit
// service that is running in our own process, we can
// cast its IBinder to a concrete class and directly access it.
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
while (mService.getThreadHandler() == null){
try {
Thread.sleep(100);
if(D) {Log.d(TAG, "Thread Handler is not ready");};
} catch (Exception e){}
}
mThreadHandler = mService.getThreadHandler();
mService.setHandler(new MainHandler(Looper.getMainLooper()));
}
线程代码。这个线程在服务中运行:
我知道,这个线程类非常“肮脏”,不优雅且不专业....
private class ThreadHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case MAIN_HANDLER:
if(D) {Log.d(TAG, "main hadler received");};
break;
}
super.handleMessage(msg);
}
}
public LocationThread (Context context){
mContext = context;
keepOn = true;
}
public void cancel() {
keepOn = false;
if (D){Log.d(TAG, "thread was canceled");};
}
public void run(){
try {
Looper.prepare();
} catch (Exception e) {}
// create handler for communication
mThreadHandler = new ThreadHandler();
// setup location updates
Location mLocation;
Location lastLocation = null;
PolylineOptions mPolylineOptions = new PolylineOptions();
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); // Use high accuracy
mLocationRequest.setInterval(UPDATE_INTERVAL); // Set the update interval to 5 seconds
mLocationRequest.setFastestInterval(FASTEST_INTERVAL); // Set the fastest update interval to 1 second
mLocationClient = new LocationClient(mContext, this, this);
mLocationClient.connect();
while (keepOn){
try {
Thread.sleep(10000);
} catch (Exception e){}
if (mConnected){
if (D) {Log.d(TAG, "thread is running");};
mLocation = mLocationClient.getLastLocation();
if (lastLocation == null) {
LatLng mLatLng = new LatLng(mLocation.getLatitude(), mLocation.getLongitude());
mPolylineOptions.add(mLatLng);
lastLocation = mLocation;
}
// Report to the UI that the location was updated
float distance = mLocation.distanceTo(lastLocation);
if (distance > 1){
LatLng mLatLng = new LatLng(mLocation.getLatitude(), mLocation.getLongitude());
mPolylineOptions.add(mLatLng);
new Color();
lastLocation = mLocation;
}
if (hasBindedActivity){
Bundle bundle = new Bundle();
bundle.putParcelable("polylineOptions", mPolylineOptions);
Message msg = Message.obtain(null, LOCATION_UPDATE);
msg.setData(bundle);
mMainHandler.dispatchMessage(msg);
}
}
}
Looper.loop();
}
答案 0 :(得分:0)
对我来说,看起来你的mMainHandler
是在GUI线程之外构建的。确保从GUI线程中调用mMainHandler = new MainHandler();
,因为Handler
回调是在创建Handler
的线程中执行的。
编辑:正如Robin所说,只要您计划根据某些后台活动更新UI,就应该使用AsyncTask
代替服务。只需在AsyncTask
中创建一个扩展Activity
的私有类,在doInBackground
中执行后台操作,然后在onPostExecute
中更新GUI,该GUI在GUI线程中再次运行。有关详细信息,请参阅http://developer.android.com/reference/android/os/AsyncTask.html。
答案 1 :(得分:0)
答案 2 :(得分:0)
显然是命令mMainHandler.dispatchMessage(msg);在错误的线程(工作线程)上执行Handlers handleMessage方法。 Documantation说“dispatchMessage(Message msg) 在此处理系统消息。“ 我必须使用sendMessage(Message msg)“在当前时间之前的所有待处理消息之后将消息推送到消息队列的末尾。”