Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách lưu trạng thái Activity Android bằng onSaveInstanceState

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

  1. Nhấn Run → nhập văn bản vào EditText.
  2. Xoay màn hình (Ctrl+F11 trên emulator) hoặc đổi ngôn ngữ/hình thức.
  3. Activity bị tạo lại → văn bản vẫn giữ nguyên, TextView hiển thị "Đã khôi phục: ...".

Cách lưu trạng thái Activity Android bằng onSaveInstanceState

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ước onStop() (trước đây là trước onPause()).