mMap.addPolyline 抛出非法状态异常
Posted
技术标签:
【中文标题】mMap.addPolyline 抛出非法状态异常【英文标题】:mMap.addPolyline throws illegalstateexception 【发布时间】:2013-10-28 21:02:30 【问题描述】:我有一个服务,它监听位置变化并将消息与 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();
【问题讨论】:
根据这段代码,整个 getThreadHandler 对我来说似乎是不必要的。我认为你可以首先为你的 MainHandler 使用没有参数的构造函数(不需要给它循环器)。然后只需从 onServiceConnected(在 UI 线程上运行)调用mMainHandler = new MainHandler();
来创建一个新的处理程序。
Hmm.. 在发布此问题之前,我尝试创建 mMainHandler 而没有提供任何循环器。结果还是一样。
你能添加整个代码吗?例如,现在我只能看到 mThreadHandler
正在初始化,但未显示 mMainHandler
的构造函数。
【参考方案1】:
没有主线程就无法更改 UI。 如果你真的想不使用AsyncTask
也许this 会有所帮助。
【讨论】:
好吧,我想我已经在你的链接上实现了类似的东西。而且不知何故它不起作用。我以前也这样做过,但不知道为什么这次不行。【参考方案2】:对我来说,您的 mMainHandler
似乎是在 GUI 线程之外构建的。确保从 GUI 线程中调用 mMainHandler = new MainHandler();
,因为 Handler
回调是在创建 Handler
的线程中执行的。
编辑:正如 Robin 所说,只要您只是计划根据一些后台活动更新 UI,您应该使用例如 AsyncTask
而不是服务。只需在您的Activity
中创建一个扩展AsyncTask
的私有类,在doInBackground
中执行背景操作,然后在onPostExecute
中更新GUI,它会在GUI 线程中再次运行。请参阅http://developer.android.com/reference/android/os/AsyncTask.html 了解更多信息。
【讨论】:
我创建 Handler 并将其传递给我的 onServiceConnected 方法上的服务。可以吗? 感谢有关 asyncTask 的建议,但这次我真的需要服务。任何想法为什么我的实施不起作用?我是否以正确的方式创建 Handler? 好的,但是为什么您需要为此提供服务呢?无论如何,这里还有一个可能有帮助的问题:***.com/questions/14695537/… 即使在应用程序被杀死后,服务也应该监听位置更新。我知道,也许这不是一个好主意,因为耗电量,也许还有其他方法可以在没有服务的情况下做到这一点,但我觉得我快要完成了,我只需要在收到位置更新后更新我的 UI。跨度> 但如果应用不再可见,则无需更新 GUI。所以我会尝试解耦逻辑:使用服务来接收位置更新并将该信息存储在某处(例如数据库)。然后在您的 GUI 代码中,例如,AsyncTask
检查是否有可用的新信息并相应地更新 GUI。【参考方案3】:
显然是命令 mMainHandler.dispatchMessage(msg);在错误的线程(工作线程)上执行 Handlers 的 handleMessage 方法。文档说 "dispatchMessage(Message msg) 在此处处理系统消息。” 我必须使用 sendMessage(Message msg) “在当前时间之前的所有待处理消息之后,将消息推送到消息队列的末尾。”
【讨论】:
以上是关于mMap.addPolyline 抛出非法状态异常的主要内容,如果未能解决你的问题,请参考以下文章
Crashlytics.logException 方法抛出非法状态异常。无法收集某些活动的非致命问题
获取 mediaMetadataRetriever.setDataSource 抛出非法参数异常
mediaMetadataRetriever.setDataSource(getBaseContext(),uri) 抛出非法参数异常