mMap.addPolyline抛出illegalstateexception

时间:2013-10-28 21:02:31

标签: java android multithreading

我有一个服务,它会监听位置更改并将消息与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();
    }

3 个答案:

答案 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)

如果没有主线程,您无法更改UI。 如果你真的想在不使用AsyncTask

的情况下这样做

也许this会有所帮助。

答案 2 :(得分:0)

显然是命令mMainHandler.dispatchMessage(msg);在错误的线程(工作线程)上执行Handlers handleMessage方法。 Documantation说“dispatchMessage(Message msg) 在此处理系统消息。“ 我必须使用sendMessage(Message msg)“在当前时间之前的所有待处理消息之后将消息推送到消息队列的末尾。”