Mặc dù hệ điều hành Android dường như không có cơ chế giải quyết đủ vấn đề của bạn, tôi tin rằng mẫu này cung cấp một cách giải quyết tương đối đơn giản.
Lớp sau là một lớp bao bọc xung quanh android.os.Handler
bộ đệm thông báo khi một hoạt động bị tạm dừng và phát lại chúng khi tiếp tục.
Đảm bảo bất kỳ mã nào bạn có mà thay đổi không đồng bộ trạng thái phân mảnh (ví dụ: cam kết, loại bỏ) chỉ được gọi từ một thông báo trong trình xử lý.
Truy xuất trình xử lý của bạn từ PauseHandler
lớp.
Bất cứ khi nào hoạt động của bạn nhận được onPause()
cuộc gọi PauseHandler.pause()
và onResume()
cuộc gọi PauseHandler.resume()
.
Thay thế việc triển khai Trình xử lý của bạn handleMessage()
bằng processMessage()
.
Cung cấp một triển khai đơn giản storeMessage()
luôn trả về true
.
/**
* Message Handler class that supports buffering up of messages when the
* activity is paused i.e. in the background.
*/
public abstract class PauseHandler extends Handler {
/**
* Message Queue Buffer
*/
final Vector<Message> messageQueueBuffer = new Vector<Message>();
/**
* Flag indicating the pause state
*/
private boolean paused;
/**
* Resume the handler
*/
final public void resume() {
paused = false;
while (messageQueueBuffer.size() > 0) {
final Message msg = messageQueueBuffer.elementAt(0);
messageQueueBuffer.removeElementAt(0);
sendMessage(msg);
}
}
/**
* Pause the handler
*/
final public void pause() {
paused = true;
}
/**
* Notification that the message is about to be stored as the activity is
* paused. If not handled the message will be saved and replayed when the
* activity resumes.
*
* @param message
* the message which optional can be handled
* @return true if the message is to be stored
*/
protected abstract boolean storeMessage(Message message);
/**
* Notification message to be processed. This will either be directly from
* handleMessage or played back from a saved message when the activity was
* paused.
*
* @param message
* the message to be handled
*/
protected abstract void processMessage(Message message);
/** {@inheritDoc} */
@Override
final public void handleMessage(Message msg) {
if (paused) {
if (storeMessage(msg)) {
Message msgCopy = new Message();
msgCopy.copyFrom(msg);
messageQueueBuffer.add(msgCopy);
}
} else {
processMessage(msg);
}
}
}
Dưới đây là một ví dụ đơn giản về cách PausedHandler
lớp có thể được sử dụng.
Khi nhấp vào một nút, một thông báo trì hoãn sẽ được gửi đến trình xử lý.
Khi trình xử lý nhận được thông báo (trên chuỗi giao diện người dùng), nó sẽ hiển thị a DialogFragment
.
Nếu PausedHandler
lớp không được sử dụng, IllegalStateException sẽ được hiển thị nếu nút trang chủ được nhấn sau khi nhấn nút kiểm tra để khởi chạy hộp thoại.
public class FragmentTestActivity extends Activity {
/**
* Used for "what" parameter to handler messages
*/
final static int MSG_WHAT = ('F' << 16) + ('T' << 8) + 'A';
final static int MSG_SHOW_DIALOG = 1;
int value = 1;
final static class State extends Fragment {
static final String TAG = "State";
/**
* Handler for this activity
*/
public ConcreteTestHandler handler = new ConcreteTestHandler();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public void onResume() {
super.onResume();
handler.setActivity(getActivity());
handler.resume();
}
@Override
public void onPause() {
super.onPause();
handler.pause();
}
public void onDestroy() {
super.onDestroy();
handler.setActivity(null);
}
}
/**
* 2 second delay
*/
final static int DELAY = 2000;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (savedInstanceState == null) {
final Fragment state = new State();
final FragmentManager fm = getFragmentManager();
final FragmentTransaction ft = fm.beginTransaction();
ft.add(state, State.TAG);
ft.commit();
}
final Button button = (Button) findViewById(R.id.popup);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final FragmentManager fm = getFragmentManager();
State fragment = (State) fm.findFragmentByTag(State.TAG);
if (fragment != null) {
// Send a message with a delay onto the message looper
fragment.handler.sendMessageDelayed(
fragment.handler.obtainMessage(MSG_WHAT, MSG_SHOW_DIALOG, value++),
DELAY);
}
}
});
}
public void onSaveInstanceState(Bundle bundle) {
super.onSaveInstanceState(bundle);
}
/**
* Simple test dialog fragment
*/
public static class TestDialog extends DialogFragment {
int value;
/**
* Fragment Tag
*/
final static String TAG = "TestDialog";
public TestDialog() {
}
public TestDialog(int value) {
this.value = value;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View inflatedView = inflater.inflate(R.layout.dialog, container, false);
TextView text = (TextView) inflatedView.findViewById(R.id.count);
text.setText(getString(R.string.count, value));
return inflatedView;
}
}
/**
* Message Handler class that supports buffering up of messages when the
* activity is paused i.e. in the background.
*/
static class ConcreteTestHandler extends PauseHandler {
/**
* Activity instance
*/
protected Activity activity;
/**
* Set the activity associated with the handler
*
* @param activity
* the activity to set
*/
final void setActivity(Activity activity) {
this.activity = activity;
}
@Override
final protected boolean storeMessage(Message message) {
// All messages are stored by default
return true;
};
@Override
final protected void processMessage(Message msg) {
final Activity activity = this.activity;
if (activity != null) {
switch (msg.what) {
case MSG_WHAT:
switch (msg.arg1) {
case MSG_SHOW_DIALOG:
final FragmentManager fm = activity.getFragmentManager();
final TestDialog dialog = new TestDialog(msg.arg2);
// We are on the UI thread so display the dialog
// fragment
dialog.show(fm, TestDialog.TAG);
break;
}
break;
}
}
}
}
}
Tôi đã thêm một storeMessage()
phương thức vào PausedHandler
lớp trong trường hợp bất kỳ thông báo nào sẽ được xử lý ngay lập tức ngay cả khi hoạt động bị tạm dừng. Nếu một thông báo được xử lý thì false sẽ được trả về và thông báo đó sẽ bị loại bỏ.