30/09/2018, 22:18

Liệu method onSaveInstanceState() được gọi trước onStop()

Mình đọc cuốn Head First Android thì nó có 1 ví dụ về stopwatch chướng 3. Ở đây nó giới thiệu về onStop() và onSaveInstanceState(), thì nó có bảo là onSaveInstanceState(Bundle saveInstanceState) sẽ được gọi trước onStop().

package com.example.tranl.stopwatch;

import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.*;
import android.widget.*;

import org.w3c.dom.Text;

public class StopwatchActivity extends AppCompatActivity {
    private int seconds = 0;
    private boolean running;
    private boolean wasRunning;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_stopwatch);
        if(savedInstanceState != null) {
            seconds = savedInstanceState.getInt("seconds");
            running = savedInstanceState.getBoolean("running");
            wasRunning = savedInstanceState.getBoolean("wasRunning");
        }
        runTimer();
    }
    @Override
    protected void onStop(){  //<------ Ở đây này
        super.onStop();
        wasRunning = running;
        running = false;
    }
    @Override
    protected void onStart(){
        super.onStart();
        if(wasRunning){
            running = true;
        }
    }
    public void onSaveInstanceState(Bundle saveInstanceState){ //<------ Ở đây này
        saveInstanceState.putInt("seconds",seconds);
        saveInstanceState.putBoolean("running",running);
        saveInstanceState.putBoolean("wasRunning",wasRunning);
    }
    public void onClickStart(View view){
        running = true;
    }
    public void onClickStop(View view){
        running = false;
    }
    public void onClickReset(View view){
        running = false;
        seconds = 0;
    }
    private void runTimer(){
        final TextView showTime = (TextView)(findViewById(R.id.showTime));
        final Handler handler = new Handler();
        handler.post(new Runnable() {
            @Override
            public void run() {
                if(running){
                    seconds++;
                    int hours = seconds/3600;
                    int minute = (seconds%3600)/60;
                    int sec = seconds%60;
                    String time = String.format("%d:%02d:%02d",hours,minute,sec);
                    showTime.setText(time);
                }
                handler.postDelayed(this,1000);
            }
        });
    }
}

file XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.tranl.stopwatch.StopwatchActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="00"
        android:textSize="92sp"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:id="@+id/showTime"
        android:layout_marginTop="0dp"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/startButton"
        android:layout_below = "@+id/showTime"
        android:text="@string/startButton"
        android:layout_centerHorizontal="true"
        android:onClick="onClickStart"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/stopButton"
        android:id="@+id/stopButton"
        android:layout_below="@+id/startButton"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="10dp"
        android:onClick="onClickStop"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/resetButton"
        android:id="@+id/resetButton"
        android:layout_below="@+id/stopButton"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="10dp"
        android:onClick="onClickReset"/>
</RelativeLayout>

onSaveInstanceState() sẽ lưu giá trị của running = true và wasrunning = false.
onStop() sẽ set wasrunning = running = true.
Mà onSaveInstanceState() được gọi trước onStop() thì giá trị của wasrunning trong Bundle là = false mới đúng chứ :v, tại sao lại là true?
Diễn đạt hơi khó hiểu nên có gì mọi người hỏi thêm phía dưới

Quân viết 00:20 ngày 01/10/2018

OnSaveInstance không có gì đảm bảo sẽ được gọi, do đó chắc gì giá trị wasRunning là do bundle restore lại

Người bị bơ viết 00:27 ngày 01/10/2018

“onSaveInstanceState() Called to retrieve per-instance state from an activity before being killed”
Ở trong trường hợp này thì mình xoay màng hình
Và nếu như không có onSaveInstanceState() thì khi nó onCreate() lại mất hết mấy cái instante state.

Bài liên quan
0