我有一个服务可以监听位置变化并将消息与 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:不在主线程上”
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();
}