1

WS から位置を取得し、GoogleMap フラグメントのマーカーを更新しようとしているので、私がやっていることは次のとおりです。

私は 2 つのフラグメント (TileOverlay を持つ 2 つの GoogleMaps) を含む HomeActivity を持っています。

私の GoogleMap フラグメントでは、マーカーの位置を OnCameraChangeListener から取得しようとしているので、ユーザーが移動するとマーカーが追加されます。

非同期リクエストに EventBus と Okhttp を使用しています。

私のGoogleMapFragment:

public class GoogleMapFragment extends FragmentBase {

@Override
public void onResume() {
    mapView.onResume();
    BusHelper.register(this); // Register the EventBus with my helper
    super.onResume();
}

@Override
public void onPause() {
    BusHelper.unregister(this); // Unregister the EventBus with my helper
    super.onPause();
}

public GoogleMap.OnCameraChangeListener getCameraChangeListener() {
    return new GoogleMap.OnCameraChangeListener() {
        @Override
        public void onCameraChange(CameraPosition cameraPosition) {

           //those are corners of visible region
            VisibleRegion visibleRegion = mMap.getProjection().getVisibleRegion();
            LatLng farLeft = visibleRegion.farLeft;
            LatLng farRight = visibleRegion.farRight;
            LatLng nearLeft = visibleRegion.nearLeft;
            LatLng nearRight = visibleRegion.nearRight;

            double minY = nearLeft.latitude;
            double minX = nearLeft.longitude;
            double maxY = farRight.latitude;
            double maxX = farRight.longitude;

            //Send the WS Request to a manager who uses okhttp              
            ApiManager.getPositions(minX, minY, maxX, maxY);
        }
    };
}

//Receive the eventBus event
public void onEvent(GetPositionsEvent event) {
    if (event.positions != null)
        setMarkersByVisibleRegion(event.positions);
}

この後、APIManager で WS Request を実行します。

public class IMSApiManager {
private final static Gson gson = new Gson();
private static Positions mPositions;

/**
 * @return Positions
 */
public static void getPositions(double minX, double minY, double maxX, double maxY) {
    String TAG = "getPositions";

    String wSRequest = AppConstants.REQUEST_POSITIONS
            .replace("{vUser}", "CARREPH1")
            .replace("{vMinX}", new BigDecimal(minX).toPlainString())
            .replace("{vMinY}", new BigDecimal(minY).toPlainString())
            .replace("{vMaxX}", new BigDecimal(maxX).toPlainString())
            .replace("{vMaxY}", new BigDecimal(maxY).toPlainString());

    try {
        RestAsyncHttpClient.doGetRequest(wSRequest, new GetPositionsCallback() {
            @Override
            public void onFailure(Request request, IOException e) {
                super.onFailure(request, e);
            }

            @Override
            public void onResponse(Response response) throws IOException {
                super.onResponse(response);
                mPositions = gson.fromJson(response.body().charStream(), Positions.class);
                BusHelper.post(new GetPositionsEvent(mPositions)); //Post the eventBus
            }
        });

    } catch (IOException exp) {
        LogHelper.error(TAG, "Error getting positions", exp);
    }
}

}

私は Not on the mainThread エラーに精通していますが、フラグメントの新しいインスタンスを実行せずにマーカーを追加する方法がなければ、理論的には可能です。

4

4 に答える 4

22

受け入れられた回答は、3 番目より低いバージョンでのみ機能します。他のバージョンでは、threadMode = ThreadMode.MAIN (ドキュメント)を使用する必要があります。

@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(MessageEvent event) {
    textField.setText(event.message);
}
于 2016-02-12T21:48:00.830 に答える
2

バックグラウンド スレッドで EventBus にオブジェクトをポストしようとすると、エラーが発生します。解決策は、post(...) がバックグラウンド スレッドで呼び出された場合、Handler にそれをメイン スレッドに移動させることです。

BusHelper のpost(...)メソッドをオーバーライドして、次の操作を行います。

public class BusHelper extends Bus {

    ...

    private final Handler mHandler = new Handler(Looper.getMainLooper());

    @Override
    public void post(final Object event) {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            super.post(event);
        } else {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    BusHelper.super.post(event);
                }
            });
        }
    }

    ...

}

お役に立てれば。

于 2015-03-13T20:41:34.707 に答える
2

onEvent の代わりに onEventMainThread を使用してください。それは私の問題も解決しました。

// Called in Android UI's main thread
public void onEventMainThread(MessageEvent event) {
    textField.setText(event.message);
}

なんで?onEvent は同じスレッドで呼び出されるため、コードを MainThread で実行する必要があります。

于 2015-03-14T04:12:41.570 に答える
0

イベントバスのオブジェクトで post を呼び出すことができます (バックグラウンド スレッドが成功した場合)。post の引数は任意のクラスのオブジェクトであるため、バックグラウンド スレッドからの結果を保持する要件に従ってカスタム クラスを設計します。

アクティビティ (UI 作業を行う必要がある場所) で、次のように定義するだけです。

public void onEventMainThread(final CobbocEvent event)
{  
    if (event.getType() == CobbocEvent.POSITION)
    {  //If background work is success
        if (event.getStatus())
        {
           //Do UI Stuff on main thread
        }
    }
}

CobbocEvent は、バックグラウンド スレッドの結果データを格納するためのカスタム クラスです。

public class CobbocEvent{
 public CobbocEvent(int type) {
    this(type, true, null);
}

public CobbocEvent(int type, boolean status) {
    this(type, status, null);
}

public CobbocEvent(int type, boolean status, Object value) {
    TYPE = type;
    STATUS = status;
    VALUE = value;
}
public CobbocEvent(int type, boolean status, int value) {
    TYPE = type;
    STATUS = status;
    VALUE = value;
}
....

私はあなたが写真を手に入れると確信しています:)

于 2015-03-14T06:44:05.773 に答える