แม้ว่าระบบปฏิบัติการ Android จะไม่มีกลไกที่ช่วยแก้ปัญหาของคุณได้อย่างเพียงพอ แต่ฉันเชื่อว่ารูปแบบนี้ให้วิธีแก้ปัญหาที่ค่อนข้างง่าย
ชั้นเรียนต่อไปนี้เป็นเสื้อคลุมรอบ ๆandroid.os.Handler
ที่บัฟเฟอร์ข้อความเมื่อกิจกรรมถูกหยุดชั่วคราวและเล่นกลับในประวัติย่อ
ตรวจสอบให้แน่ใจว่าโค้ดใด ๆ ที่คุณมีซึ่งเปลี่ยนสถานะแฟรกเมนต์แบบอะซิงโครนัส (เช่นคอมมิต, ปิด) ถูกเรียกจากข้อความในตัวจัดการเท่านั้น
รับตัวจัดการของคุณจากPauseHandler
คลาส
เมื่อใดก็ตามที่กิจกรรมของคุณได้รับการonPause()
โทรPauseHandler.pause()
และการโทรonResume()
PauseHandler.resume()
แทนที่การดำเนินงานของคุณจัดการกับhandleMessage()
processMessage()
จัดให้มีการดำเนินงานที่เรียบง่ายของซึ่งมักจะให้ผลตอบแทนstoreMessage()
true
public abstract class PauseHandler extends Handler {
final Vector<Message> messageQueueBuffer = new Vector<Message>();
private boolean paused;
final public void resume() {
paused = false;
while (messageQueueBuffer.size() > 0) {
final Message msg = messageQueueBuffer.elementAt(0);
messageQueueBuffer.removeElementAt(0);
sendMessage(msg);
}
}
final public void pause() {
paused = true;
}
protected abstract boolean storeMessage(Message message);
protected abstract void processMessage(Message message);
@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);
}
}
}
ด้านล่างนี้เป็นตัวอย่างง่ายๆของวิธีการใช้PausedHandler
คลาส
เมื่อคลิกปุ่มข้อความล่าช้าจะถูกส่งไปยังตัวจัดการ
เมื่อตัวจัดการได้รับข้อความ (บนเธรด UI) จะแสดงไฟล์DialogFragment
.
หากPausedHandler
ไม่ได้ใช้คลาส IllegalStateException จะแสดงขึ้นหากกดปุ่มโฮมหลังจากกดปุ่มทดสอบเพื่อเปิดกล่องโต้ตอบ
public class FragmentTestActivity extends Activity {
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";
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);
}
}
final static int DELAY = 2000;
@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) {
fragment.handler.sendMessageDelayed(
fragment.handler.obtainMessage(MSG_WHAT, MSG_SHOW_DIALOG, value++),
DELAY);
}
}
});
}
public void onSaveInstanceState(Bundle bundle) {
super.onSaveInstanceState(bundle);
}
public static class TestDialog extends DialogFragment {
int value;
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;
}
}
static class ConcreteTestHandler extends PauseHandler {
protected Activity activity;
final void setActivity(Activity activity) {
this.activity = activity;
}
@Override
final protected boolean storeMessage(Message message) {
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);
dialog.show(fm, TestDialog.TAG);
break;
}
break;
}
}
}
}
}
ฉันได้เพิ่มstoreMessage()
วิธีการในPausedHandler
ชั้นเรียนแล้วในกรณีที่ข้อความใด ๆ ควรได้รับการประมวลผลทันทีแม้ว่ากิจกรรมจะหยุดชั่วคราว หากมีการจัดการข้อความแล้วควรส่งคืนเท็จและข้อความจะถูกทิ้ง