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: 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();
    }
4

3 に答える 3

0

私にとっては、あなたmMainHandlerはGUIスレッドの外で構築されているようです。コールバックは が作成されたスレッドで実行されるmMainHandler = new MainHandler();ため、必ず GUI スレッド内から呼び出すようにしてください。HandlerHandler

編集: ロビンが言ったように、何らかのバックグラウンド アクティビティに基づいて UI を更新することを計画している限り、たとえばAsyncTaskサービスの代わりにを使用する必要があります。AsyncTask内で拡張するプライベート クラスを作成Activityし、 でバックグラウンド処理を行ってdoInBackgroundから、 で GUI を更新しonPostExecuteます。これは、GUI スレッドで再び実行されます。詳細については、 http://developer.android.com/reference/android/os/AsyncTask.htmlを参照してください。

于 2013-10-28T21:10:55.523 に答える
0

メインスレッドなしで UI を変更することはできません。AsyncTaskを使用せずに本当にやりたい場合

多分これが役立つでしょう。

于 2013-10-28T21:15:03.103 に答える