天天看點

安卓——Activity的生命周期安卓的Activity活動棧安卓Activity的活動狀态Activity活動狀态切換觸發回調方法代碼:PS:手機的橫豎屏轉換時的問題

安卓的Activity活動棧

多個安卓Activity中的先後次序問題,需要用活動棧機制

安卓——Activity的生命周期安卓的Activity活動棧安卓Activity的活動狀态Activity活動狀态切換觸發回調方法代碼:PS:手機的橫豎屏轉換時的問題

如圖:

  1. 每當新打開一個Activity時,會入棧,此時隻有這個Activity是活動狀态
  2. 除了棧頂的Activity其餘的都處于暫停或者停止狀态
  3. 如果記憶體不足,需要殺死Activity時,會釋放資源使Activity處于非活動狀态

安卓Activity的活動狀态

分為四種:

  1. 活動狀态:在活動棧處于棧頂的Activity,能被使用者看到且可以互動,簡單來說就是螢幕目前的Activity
  2. 暫停狀态:目前Activity被部分遮擋,不再處于活動棧棧頂,并且無法互動。這裡的部分遮擋是要被Activity遮擋,彈出框之類的不算被遮擋
  3. 停止狀态:目前Activity被完全遮擋。比如按下HOME鍵或者跳轉到别的頁面
  4. 非活動狀态:不是上面三種狀态的Activity,例如被銷毀的Activity

Activity活動狀态切換觸發回調方法

安卓——Activity的生命周期安卓的Activity活動棧安卓Activity的活動狀态Activity活動狀态切換觸發回調方法代碼:PS:手機的橫豎屏轉換時的問題

如圖,轉化過程如下:

  1. 當Activity生成時調用onCreate、onStart、onResume(相當于可以互動了),之後Activity開始運作
  2. 如果Acttvity處于暫停狀态,會調用onPause
  3. Acitivty重新可以互動時調用onResume
  4. Activity變成停止狀态,調用onPause和onStop
  5. Activity從停止狀态變成活動狀态,會調用onRestart和onStart和onResume方法
  6. 目前Activity從活動狀态直接被銷毀依次調用onPause、onStop、onDestory
  7. 當Activity處于暫停狀态或者停止狀态時,如果記憶體不足需要殺死Activty,程序終止,再打開需要重新生成

代碼:

package net.onest.activitych0402;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;

public class MainActivity extends AppCompatActivity {

    private EditText etMsg;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.e("MainActivity","onCreate");
        etMsg = findViewById(R.id.et_msg);
        if (null != savedInstanceState){
            Log.e("onCreate",savedInstanceState.getString("msg"));
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.e("MainActivity","onStart");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.e("MainActivity","onRestart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.e("MainActivity","onResume");
        //将資料進行恢複(讀取檔案,查詢資料庫等)
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.e("MainActivity","onPause");
        //将頁面的使用者資料進行儲存(檔案、資料庫中)
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.e("MainActivity","onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.e("MainActivity","onDestroy");
    }

    public void buttonClicked(View view) {
        switch (view.getId()){
            case R.id.btn_dialog:
                Intent intent = new Intent();
                intent.setClass(MainActivity.this,
                        DialogActivity.class);
                startActivity(intent);
                break;
            case R.id.btn_new:
                Intent intent1 = new Intent();
                intent1.setClass(MainActivity.this,
                        NewActivity.class);
                startActivity(intent1);
//                finish();
                break;
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        Log.e("MainActivity","onSaveInstanceState");
        super.onSaveInstanceState(outState);
        //儲存使用者資料
        outState.putString("msg",etMsg.getText().toString());
    }

    @Override
    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
        Log.e("MainActivity","onRestoreInstanceState");
        super.onRestoreInstanceState(savedInstanceState);
        //恢複使用者資料
        String content = savedInstanceState.getString("msg");
        //顯示到界面
        etMsg.setText(content);
    }
}

           

PS:

1. 如果想處于暫停狀态,需要一個Activity覆寫到目前的Activity上面,并且不是完全覆寫,操作如下:

在資源目錄下的values的styles.xml檔案中,寫一個樣式,例如:

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
	// 這裡item是定義自己獨特的地方的标簽,我們需簡要吧windowIsFloating設定為true
    <style name="DialogActivity" parent="AppTheme">
        <item name="android:windowIsFloating">true</item>
    </style>

</resources>
           

在manifests中設定activity的樣式

<activity
            android:name=".DialogActivity"
            android:theme="@style/DialogActivity" /> <!--此處樣式改成上面寫好的那個-->
           

跳轉到這樣生成的Activity上,原來的就會處于暫停狀态

2.

在傳回時使用finish方法結束目前Activity,而不是去跳轉回原來的Activity,

如果跳轉回去就會産生兩個不一樣的Activity

// 比如我從MainActivity跳轉到NewActivity
	Intent intent = new Intent();
	intent.setClass(MainActivity.this,NewActivity.class);
	startActivity(intent);
	// 如果在NewActivity中使用finish方法就會回到MainActivity中,并且隻有一個
	// 如果用下面的這種方法,會産生兩個MainActivity,假如第一個Activity中已經寫好部分資訊,跳轉回去産生新的MainActivity中不會有那部分資訊 
    Intent intent = new Intent();
    intent.setClass(NewActivity.this,MainActivity.class);
    startActivity(intent);	
           

3.ToolBar工具欄

我們需要在XML中先設定一個樣式=>沒有ActivityBar的樣式

資源位置還在剛才的styles.xml檔案中寫

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> => 此處parent為重點
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>
           

然後在布局中添加一個ToolBar(需要有這個的布局中寫)

<androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        app:title="新的Activity"
        app:navigationIcon="@drawable/back"/> => 這個地方設定傳回按鈕
           

最後在java代碼中替換掉ActivityBar

Toolbar toolbar = (Toolbar) findViewById(R.id.toolBar); // 找到元件
	toolbar.setTitle("ToolBarDemo"); // 設定标題
	setSupportActionBar(toolbar); // 替換
           

手機的橫豎屏轉換時的問題

當橫豎屏轉換時,會将原來的Activity銷毀,産生一個新的Activity,導緻的問題是原來寫好的内容沒了。

此時有兩種方法可以解決:

  1. 借助onPause和onRestart方法将資料存到文本或者資料庫中
  2. 借助兩個回調方法臨時保持狀态(第一個方法也是兩個回調方法,不是那兩個)

第二種的實作方式為重寫onSaveInstanceState和onRestoreInstanceState方法,兩個方法都有參數Bundle,借助于Bundle存鍵值對即可,例如:

@Override
    protected void onSaveInstanceState(Bundle outState) {
        Log.e("MainActivity","onSaveInstanceState");
        super.onSaveInstanceState(outState);
        //儲存使用者資料
        outState.putString("msg",etMsg.getText().toString());
    }

    @Override
    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
        Log.e("MainActivity","onRestoreInstanceState");
        super.onRestoreInstanceState(savedInstanceState);
        //恢複使用者資料
        String content = savedInstanceState.getString("msg");
        //顯示到界面
        etMsg.setText(content);
    }
           

PS:onCreate的參數Bundle和這兩個回調方法的Bundle是同一個對象