Android開發學習一:界面組件Activity

《Android開發實戰 從學習到產品》李瑞琪編著 學習筆記。

Android最常見四組件:Activity、Service、ContentProvider、BroadcastReceiver。
Activity:Android開發最重要的組件,Android應用程序界面,凡是在應用中能看到的東西都是放在Activity中的。

一、Activity生命週期

1、概述

Activityt由Activity棧進行管理,新Activity將被加到Activity棧頂,之前的Activity將位於該新Activity底部。Activity的四種狀態:

  • 當Activity位於棧頂,處於屏幕最前方,運行狀態
  • 當Activity失去焦點但任對用戶可見(棧頂Activity透明或未鋪滿屏幕等),暫停狀態
  • 當Activity完全被其他Activity遮擋時,Activity對用戶不可見,處於停止狀態
  • 當Activity被人爲或系統原因銷燬,處於銷燬狀態

開發過程中寫的Activity一般都繼承Activity類並重寫相應的回調方法,Activity生命週期流程圖如下:

Activity生命週期流程圖

由圖知Activity生命週期的7個事件:

  • onCreate():Activity第一次被創建時調用,可在此方法中綁定數據或創建其他視圖控件。
  • onStart():當Activity變爲用戶可見之前調用。
  • onResume():當Activity可以與用戶交互之前調用,即Activity對象到達Activity棧頂即將成爲前臺進程時調用。
  • onPause():當系統調用其他Activity對象時調用(注:新Activity對象必須等待該方法執行完畢再顯示出來,多數情況下onPause()方法要關閉onResume()中打開的方法)。
  • onStop():當Activity不可視時調用。
  • onDestroy():當銷燬Activity對象時調用。
  • onRestart():當處於onStop()狀態的Activity又變爲可視時調用。

除這些方法外,還有3個關鍵的週期循環:

  • Activity的完整週期 從第一次調用onCreate(Bundle)設置所有“全局"狀態及完成初始化開始,直至調用onDestroy()釋放所有系統資源。
  • Activity的可視生命週期 自onStart()調用開始至onStop()調用爲止,用戶屏幕可見此Activity。
  • Activity前臺生命週期 自onResume()調用起,至onPause()調用爲止,該期間Activity位於前臺最上面並與用戶進行交互。

2、實例:

package com.example.day0907_lifeactivity;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    protected void onDestroy(){
        super.onDestroy();
        Log.i("LifeActivity","onDestroy");
    }

    protected void onPause(){
        super.onPause();
        Log.i("LifeActivity","onPause");
    }

    protected void onResume(){
        super.onResume();
        Log.i("LifeActivity","onResume");
    }

    protected void onRestart(){
        super.onRestart();
        Log.i("LifeActivity","onRestart");
    }

    protected void onStart(){
        super.onStart();
        Log.i("LifeActivity","onStart");
    }

    protected void onStop(){
        super.onStop();
        Log.i("LifeActivity","onStop");
    }


    /*onWindowFocusChanged()方法:在Activity窗口獲得或失去焦點時被調動
    (在onResume()之後或onPause()之後調用)*/
    public void onWindowFocusChanged(boolean hasFocus){
        super.onWindowFocusChanged(hasFocus);
        Log.i("LifeActivity","onWindowFocusChanged");
    }

    /*在Activity被覆蓋或退居後臺之後,系統資源不足將其殺死時;用戶改變屏幕方向;
    當前Activity跳轉到其他Activity或按Home鍵回到主屏,自身退居後臺時 被調用
    調用在onPause()之前*/
    protected void onSaveInstanceState(Bundle outState){
        Log.i("LifeActivity","onSaveInstanceState");
        super.onSaveInstanceState(outState);
    }

    /*當Activity被覆蓋或局後臺,系統資源不足將其殺死,然後用戶又回到Activity時;
    * 用戶改變屏幕方向重建過程中 被調用。調用在onStart()之後*/
    protected void onRestoreInstanceState(Bundle savedInstanceState){
        Log.i("LifeActivity","onRestoreInstanceState");
        super.onRestoreInstanceState(savedInstanceState);
    }
}

點擊Android Studio左下角logcat查看日誌(設置查看日誌level爲info,關鍵字爲LifeActivity):

(1).初次運行Activity時:系統調用onCreate和onStart後調用onResume,Activity進入運行狀態。
在這裏插入圖片描述
(2).在模擬機上按Home鍵回主屏幕或跳轉Activity:退居後臺後,Activity窗口焦點發生變化,故先調用onWindowFocusChanged方法,再依次調用各個方法。
在這裏插入圖片描述

(3).重回原Activity:先調用onRestart方法使用戶可見,再調用…
在這裏插入圖片描述
(4). 退出程序:最後調用的onDestroy方法銷燬Activity。
在這裏插入圖片描述(5).橫屏:期間調用了一次onDestroy方法銷燬Activity及onStart方法打開Activity,故調用了一次onSaveInstanceState方法保存臨時數據,和一次onRestoreInstanceState方法恢復數據。
在這裏插入圖片描述

二、Intent與Activity之間的跳轉

Intent:完成組件之間的通信。(此處僅介紹完成Activity間的通信),Intent應用場合主要三種:
①.啓動一個Activity。
②.啓動一個Service。
③.啓動一個BroadCast。

當使用一個Intent進行組件通信時,需要先實例化一個Intent對象,此時需要設置Intent屬性

Action(要執行的動作):如ACTION_CALL表示撥打電話、ACTION_EDIT表示調用編輯器、ACTION_SYNC表示同步數據…
Data(執行動作所操作的數據):在Intent中使用指向數據的URI來表示。
Type(顯示指定Intent數據類型):不同動作URI數據類型不同。
Category(執行動作的附加信息)
Component(指定Intent目標組件的類名稱):通常Android根據Intent包含的上述等屬性進行查找,若設置該屬性則查找過程不需執行。
Extras(其他所有附加信息的集合):爲組件提供擴展信息。

另外,使用Intent時根據是否明確指定Intent對象的接收者,分顯示(即在構造Intent對象時就指定接受者)和隱式(在構造Intent對象時不指定接受者,Android需對其進行解析:查找AndroidManifest.xml文件中所有IntentFilter及其定義的Intent,找到最匹配的Intent【判斷Intent的Action、Type、Category找到最匹配的Intent】)的Intent。

1.顯式意圖

要求必須知道被激活組件的包和class
在該項目內創建新Empty Activity(new->)取名爲SecondaryActivity,在activity_secondary.xml內放置一個TextView控件編輯其text內容爲“第二個Activity!”以作標記。
在activity_main.xml內放置一個Button按鈕,使得單擊跳轉到SecondaryActivity界面,並在MainActivity.java內代碼實現跳轉功能

package com.example.day0907_lifeactivity;

import android.content.Intent;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.os.Bundle;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    private Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //R類:將Android的資源文件存儲爲鍵值對的一個類(系統自建,勿改),findViewById獲得View控件對象的方法
        button = (Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener(){
            public void onClick(android.view.View view){
                //跳轉到第二個Activity
                gotoSecondaryActivity();
            }
        });
    }

    private void gotoSecondaryActivity(){
        Intent toSecondary = new Intent();      //創建一個意圖
        toSecondary.setClass(this,SecondaryActivity.class);//指定跳轉SecondaryActivity
        toSecondary.putExtra("name","Ricky");    //設置傳遞字符串
        toSecondary.putExtra("age",25);         //設置傳遞int類型內容
        //上述兩行代碼可改爲如下代碼  android中使用Bundle來共享變量
//        Bundle bundle = new Bundle();
//        bundle.putString("name","Ricky");
//        bundle.putInt("age",25);
//        toSecondary.putExtras(bundle);
        startActivity(toSecondary);
    }


}

SecondaryActivity.java內代碼接受數據

package com.example.day0907_lifeactivity;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

public class SecondaryActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_secondary);

        Intent intent_accept = getIntent();     //創建一個接收意圖
        Bundle bundle = intent_accept.getExtras();      //創建一個Bundle對象用於接收Intent數據
        String name = bundle.getString("name");     //獲取Intent的內容name
        int age = bundle.getInt("age");     //獲取Intent的內容age
        Log.i("SencodaryActivity", name + " " + age);
    }
}

程序效果圖
在這裏插入圖片描述

2.隱式意圖

*可以不知道被激活組件的包和class,只通過指定action就進行跳轉,如果一個Activity想要啓動另一個應用的Activity就只能使用隱式意圖

3.帶回調方法的意圖

有時需定義在MainActivity中的某一控件啓動SecondaryActivity並當SecondaryAActivity結束時返回給MainActivity一個執行結果。

4.跳轉中對象參數的傳遞

在Android開發中,有時多個Activity之間需要進行對象的傳遞,使用Intent也可以完成這一功能。
MainActivity.java 內的gotoSecondaryActivity方法改爲:

private void gotoSecondaryActivity(){
        Intent toSecondary = new Intent();      //創建一個意圖
        toSecondary.setClass(this,SecondaryActivity.class);//指定跳轉SecondaryActivity
        Bundle bundle = new Bundle();
        User user = new User();
        user.setAge(25);
        user.setName("Ricky");
        bundle.putSerializable("user",user);
        toSecondary.putExtras(bundle);
        startActivity(toSecondary);
        //startActivityForResult(toSecondary,RequestCode);//啓動帶請求碼意圖
    }

SecondaryActivity.java 內的onCreate方法改爲

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_secondary);

        Intent intent = getIntent();    //創建接收意圖
        Bundle bundle = intent.getExtras();
        User user = (User)bundle.get("user");   //???
        Log.i("SecodaryActivity", user.getName()+" "+user.getAge());
}

則單擊第一個Activity中按鈕,日誌顯示爲:
在這裏插入圖片描述

三、Activity啓動模式

Task:以棧來管理Activity。
Activity四種啓動模式:standard、singleTop、singleTask、singleInstance。

  1. standard:默認啓動模式,若不指定launchMode屬性,就會自動使用這種啓動模式。
    聲明爲這種啓動模式的Activity可以被實例化多次,一個任務當中也可以包含多個Activity的實例。
  2. singleTop:在AndroidManifest.xml中配置的android:launchMode的屬性爲singleTop。singleTop模式,若要啓動的Activity在當前任務中已存在,且處於棧頂的位置,則系統不會再創建一個該Activity實例,而是調用棧頂Activity的onNewIntent()方法
      例:若Task返回棧中有4個Activity:A-B-C-D,D位於棧頂,A位於棧底,若要求再啓動儀一次D,若D啓動模式爲standard則系統再創建一個D實例,此棧內元素爲A-B-C-D-D;若D啓動模式爲singleTop,系統直接調用D的onNewIntent()方法,此時棧內元素任爲A-B-C-D。
  3. singleTask該啓動模式表示,系統會創建一個新任務,並將啓動的Activity放入這個新任務的底部,但是若該任務中已經存在該Activity的實例,不會新創建該Activity的實例而是調用該Activity的onNewIntent()方法,故該啓動模式下Activity在同一個任務中只會存在一個實例。
      singleTask模式默認情況下只有啓動其他應用程序的Activity纔會創建一個新任務,啓動自己程序中的Activity還是會使用相同的任務。
    在這裏插入圖片描述
  4. singleInstance:singleInstance模式啓動Activity會創建一個新的Task,這種Activity所在的Task中始終只會有一個Activity。通過這個Activity打開其他Activity會被放入別的任務當中。
      standard模式是Android默認啓動模式,可能造成多次啓動問題,如用戶手誤多次點擊一個跳轉到新Activity按鈕,系統會創建多個新Activity,而用戶只需一個。singleTop模式可避免這個問題,該模式在啓動Activity時,如果發現該返回棧中的棧頂已是該Activity時,就認爲可以直接使用它而不會創建新的Activity實例。若要啓動的Activity不在棧頂,還是會創建該Activity的實例。將啓動模式設置爲singleTask,每次啓動Activity時系統首先在返回棧中檢查是否有該Activity的實例,若有就直接使用該Activity的實例,並將這個Activity上的所有活動統統出棧,若沒有就會創建一個新的Activity。而singleInstance模式的活動將會啓用一個新的返回棧來管理這個活動,解決了多個應用訪問一個Activity時的共享問題。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章