1

我正在尝试从我的 WS 获取位置并更新我的 GoogleMap 片段中的标记,所以我正在做的是:

我的 HomeActivity 包含 2 个片段(2 个 GoogleMaps,其中一个具有 TileOverlay)。

在我的 GoogleMap 片段中,我试图从 OnCameraChangeListener 获取我的标记位置,以便在用户继续移动时添加标记。

我正在使用 EventBus 和 Okhttp 进行异步请求!

我的谷歌地图片段:

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 请求。

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

接受的答案仅适用于低于第三的版本,对于其他版本,您应该使用threadMode = ThreadMode.MAIN文档

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

只需使用 onEventMainThread 而不是 onEvent。它也解决了我的问题。

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

为什么?因为 onEvent 是在同一个线程中调用的,所以您需要在 MainThread 上运行您的代码。

于 2015-03-14T04:12:41.570 回答
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 回答
0

您可以在 eventbus 的对象上调用 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 回答