0

我有一个服务可以监听位置变化并将消息与 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();
    }
4

3 回答 3

0

对我来说,看起来你mMainHandler是在 GUI 线程之外构建的。确保mMainHandler = new MainHandler();从 GUI 线程中调用,因为Handler回调是在Handler创建的线程中执行的。

编辑:正如 Robin 所说,只要您只是计划根据一些后台活动更新 UI,您应该使用例如AsyncTask而不是服务。只需创建一个在AsyncTaskActivity的. 有关更多信息,请参阅http://developer.android.com/reference/android/os/AsyncTask.htmldoInBackgroundonPostExecute

于 2013-10-28T21:10:55.523 回答
0

没有主线程就无法更改 UI。如果你真的想在不使用AsyncTask的情况下做到这一点

也许会有所帮助。

于 2013-10-28T21:15:03.103 回答
0

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

于 2013-10-30T06:41:35.380 回答