Giới thiệu
Khi Android hủy Activity do thiếu bộ nhớ hoặc xoay màn hình (configuration change), phương thức onSaveInstanceState(Bundle) cho phép lưu trữ trạng thái tạm thời để khôi phục lại trong onCreate() hoặc onRestoreInstanceState().
Vòng đời liên quan
onCreate() → onStart() → onResume() → [Running]
↑ |
| onPause() → onStop() → onDestroy()
| |
└── onRestart() ← onStop() ←───┘
(nếu không bị kill)
Khi bị kill bởi hệ thống:
onPause() → onStop() → onSaveInstanceState() → onDestroy()
Sau đó tạo mới:
onCreate(savedInstanceState) → onStart() → onRestoreInstanceState() → onResume()
Ví dụ hoàn chỉnh
Bước 1: Giao diện (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<EditText
android:id="@+id/etInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Nhập văn bản..."
android:padding="16dp" />
<TextView
android:id="@+id/tvRestored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Dữ liệu khôi phục: "
android:textSize="18sp" />
</LinearLayout>
Bước 2: MainActivity.java
package com.example.myapplication;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private static final String KEY_SAVED_TEXT = "saved_text";
EditText etInput;
TextView tvRestored;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etInput = findViewById(R.id.etInput);
tvRestored = findViewById(R.id.tvRestored);
// Khôi phục từ onCreate (khuyên dùng)
if (savedInstanceState != null) {
String restored = savedInstanceState.getString(KEY_SAVED_TEXT, "");
etInput.setText(restored);
tvRestored.setText("Đã khôi phục: " + restored);
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// Lưu dữ liệu trước khi Activity bị hủy
outState.putString(KEY_SAVED_TEXT, etInput.getText().toString());
}
// onRestoreInstanceState được gọi SAU onStart(), TRƯỚC onResume()
// Chỉ gọi khi savedInstanceState != null
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Có thể khôi phục ở đây thay vì onCreate
String restored = savedInstanceState.getString(KEY_SAVED_TEXT, "");
tvRestored.setText("Khôi phục ở onRestore: " + restored);
}
}
Dữ liệu nên lưu trong Bundle
- Primitive types:
putInt(),putString(),putBoolean(),putParcelable(),putSerializable(). - Các đối tượng implement
Parcelable(nhanh hơn Serializable). - KHÔNG lưu: Context, View, Bitmap lớn, Database connection, Thread.
Chạy ứng dụng
- Nhấn Run → nhập văn bản vào EditText.
- Xoay màn hình (Ctrl+F11 trên emulator) hoặc đổi ngôn ngữ/hình thức.
- Activity bị tạo lại → văn bản vẫn giữ nguyên, TextView hiển thị "Đã khôi phục: ...".

Lưu ý quan trọng
onSaveInstanceState()không đảm bảo luôn được gọi (ví dụ: user bấm Back, hoặc finish()).- Dùng cho trạng thái UI tạm thời (scroll position, text nhập, lựa chọn tab).
- Dữ liệu quan trọng cần lưu bền → dùng
ViewModel,SharedPreferences, Database. - Từ API 28,
onSaveInstanceState()được gọi trướconStop()(trước đây là trướconPause()).