post 可以在旋转屏幕时丢失吗?

Can a post be lost while rotating screen?

有没有可能当我点击按钮然后等待一段时间(~5 秒)后旋转屏幕 post 可能会被错过,因为 activity 没有设法重新- 及时注册? 我相信我已经做到了。但这就像 50 次尝试中的 1 次:)

import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class MainActivity extends BaseActivity {

    @BindView(R.id.post)
    Button mPost;

    @BindView(R.id.result)
    TextView mResult;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
    }

    @Override
    protected void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        EventBus.getDefault().unregister(this);
    }

    @OnClick(R.id.post)
    void onPostClick() {

        HandlerThread handlerThread = new HandlerThread("MyThread");
        handlerThread.start();
        Handler handler = new Handler(handlerThread.getLooper());

        handler.post(new Runnable() {
            @Override
            public void run() {
                Log.e(TAG, Thread.currentThread().getName());
                try {
                    Thread.sleep(5000);
                    EventBus.getDefault().post(new MyObject("wow"));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });


    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onResult(MyObject object) {
        Log.e(TAG, "POST " + object);
    }

    static class MyObject {
        String val;

        public MyObject(String val) {
            this.val = val;
        }

        @Override
        public String toString() {
            return val;
        }
    }
}

您的 Activity 会在您旋转设备时重新创建。您可以像这样设置清单属性。 android:configChanges="orientation|keyboardHidden|screenSize"

您需要 subsribe/unsubscribe 监听器不在 onStartonStop 中,而是在 onCreateonDestroy 中。此外,post main 线程中的事件。在这种情况下,不会有间隙,如果 recteated

new activity 将收到事件

代码有可能 Activity 由于娱乐而错过了事件,但是如果这是一个问题,那么您很可能应该将事件发布为 sticky:

Some events carry information that is of interest after the event is posted. For example, an event signals that some initialization is complete. Or if you have some sensor or location data and you want to hold on the most recent values. Instead of implementing your own caching, you can use sticky events. EventBus keeps the last sticky event of a certain type in memory. The sticky event can be delivered to subscribers or queried explicitly. Thus, you don’t need any special logic to consider already available data.

http://greenrobot.org/eventbus/documentation/configuration/sticky-events/

此外,一些人建议将注册处理从 onStart/onStop 移动到 onCreate/onDestroy。我认为这是个坏主意 - 如果你在后台,你通常不关心事件,因此我还建议将 reg/unreg 代码移动到 onResume/onPause

您需要做的是使用 onSaveInstanceState() 方法重新创建 activity。

保存你的Activity状态

static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current game state
savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);

// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}

恢复你的Activity状态

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first

// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
    // Restore value of members from saved state
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
    mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
    // Probably initialize members with default values for a new instance
}
...
}