Android EventBus不在主线程上

Android EventBus不在主线程上,android,google-maps,android-fragments,greenrobot-eventbus,Android,Google Maps,Android Fragments,Greenrobot Eventbus,我试图从我的WS中获取位置,并在我的Google地图片段中更新我的标记,因此我正在做的是: 我有我的HomeActivity,它包含2个片段,2个谷歌地图,其中一个有TileOverlay 在我的GoogleMap片段中,我试图从OnCamerachenglistener获取标记位置,以便在用户继续移动时添加标记 我正在使用EventBus和Okhttp进行异步请求 我的谷歌地图片段: public class GoogleMapFragment extends FragmentBase {

我试图从我的WS中获取位置,并在我的Google地图片段中更新我的标记,因此我正在做的是:

我有我的HomeActivity,它包含2个片段,2个谷歌地图,其中一个有TileOverlay

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

我正在使用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);
    }
}
}


我熟悉非主线程错误,但在理论上这是可能的,如果不是的话,我如何在不执行片段的新实例的情况下添加标记。

当您尝试在后台线程中将对象发布到EventBus时,会出现错误。解决办法是,如果发布。。。在后台线程中调用,让处理程序将其移动到主线程

超越你的丛林人的岗位。。。方法并执行以下操作

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);
                }
            });
        }
    }

    ...

}

希望这有帮助。

当您尝试在后台线程中将对象发布到EventBus时,会出现错误。解决办法是,如果发布。。。在后台线程中调用,让处理程序将其移动到主线程

超越你的丛林人的岗位。。。方法并执行以下操作

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);
                }
            });
        }
    }

    ...

}

希望这有帮助。

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

// Called in Android UI's main thread
public void onEventMainThread(MessageEvent event) {
    textField.setText(event.message);
}
为什么??
由于在同一线程中调用了OneEvent,因此需要在主线程上运行代码。

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

// Called in Android UI's main thread
public void onEventMainThread(MessageEvent event) {
    textField.setText(event.message);
}
为什么??
由于OneEvent是在同一线程中调用的,因此您需要在主线程上运行代码。

后台线程成功后,您可以在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
        }
    }
}
CobboEvent是用于存储后台线程结果数据的自定义类:

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;
}
....

我相信您已经明白了这一点:

当后台线程成功时,您可以调用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
        }
    }
}
CobboEvent是用于存储后台线程结果数据的自定义类:

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;
}
....

我相信您已经明白了这一点:

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


Accepted answer仅适用于低于Threed的版本,对于其他版本,应使用threadMode=threadMode.MAIN


这是有道理的,但是通过eventBus文档,我能够捕捉到这样的背景事件!//在后台线程public void onEventBackgroundThreadMessageEvent事件{saveToDiskevent.message;}中调用。我假设在您的snipet中,MainBus是我的EventBus super类实例,但EventBus没有super,因此我无法完成它,但是通过eventBus文档,我能够捕捉到这样的背景事件!//在后台线程public void onEventBackgroundThreadMessageEvent事件{saveToDiskevent.message;}中调用。我假设在您的snipet中,MainBus是我的EventBus超类实例,但是EventBus没有super所以我无法完成但是@Pedro我的帖子它不是来自主线程它是一个okhttp后台线程所以它不可能在我之前的评论中,我尝试过并运行了!但从eventBus文档中,我了解到OneEvent是对OneEventMainThread的一种短路,但我错了,你是对的。这应该是正确的答案,我将删除我以前的答案,并将这一个标记为正确。葡萄牙语是一种非语言:是一种语言;我认为默认情况下,这个方法应该在库中使用。但是我不能做任何非常重要的事情来改变这个规则。如果你认为Java应用程序不是Android应用程序以不同于Android的方式运行,这是有道理的。但是@Pedro my Post它不是来自主线程,它是一个okhttp后台线程,所以它不可能。在我之前的评论中,我试过了,它运行了!但从eventBus文档中,我了解到OneEvent是对OneEventMainThread的一种短路,但我错了,你是对的。这应该是正确的答案,我将删除我以前的答案,并将这一个标记为正确。葡萄牙语是一种非语言:是一种语言;我认为默认情况下,这个方法应该在库中使用。但是我不能做任何非常重要的事情来改变这个规则。如果你认为Java应用程序而不是Android应用程序在不同的环境中运行
租用Android的方式,这是有意义的。是的,这是我所做的,我不确定性能,但周一我将进行一些测试。如果您发现在设备上处理服务器数据的更有效方法,请与我们分享。这是我所做的,我不确定性能,但周一我将运行一些测试。如果您发现在设备上处理服务器数据的更有效方法,请务必共享。这是正确的答案,因为您可以选择希望事件处理程序位于哪个线程上。这里的文档:这是针对EventBus版本3的文档,它基于注释。虽然这个答案是正确的,但对于以下任何版本,接受的答案也是正确的。这是正确的答案,因为您可以选择希望事件处理程序处于哪个线程上。这里的文档:这是针对EventBus版本3的文档,它基于注释。虽然这个答案是正确的,但对于以下任何版本,公认的答案也是正确的。