天天看點

006 Android之Activity

文章目錄

    • 四大元件之Activity
      • Activety概述
      • Activity的響應事件
      • Activity之間的資料傳遞
        • 資料傳遞執行個體
      • Activity的生命周期
      • Activity聲明周期總結
      • Activity的任務棧
      • Activity的啟動模式
        • 預設啟動模式 standard
        • 棧頂複用模式 singleTop
        • 棧内複用模式 singleTask
        • 全局唯一模式 singleInstance
    • 四大元件之紐帶Intent
      • Intent概述
      • Intent對象的組成
      • Intent過濾器(Intent Filter)
      • Intent對象的解析

四大元件之Activity

Activety概述

Activity是我們一開始學習到安卓的時候就接觸到的,在開發應用程式中,對Activity的操作分為以下幾種

  1. 對Activity本身的操作,比如我們需要做個遊戲,需要響應滑鼠事件,單擊,觸摸等事件
  2. 要想程式功能完整,Activity往往不止一個,多個Activity就涉及到他們之間的切換以及資料傳遞
  3. 在系統中往往不止一個應用程式,當我們在使用過程中,突然電話來了,界面會暫時消失,這就涉及Activity的生命周期
  4. 為了适應多種應用程式的啟動和顯示,Activity還分為幾種啟動模式

Activity的響應事件

Android平台的事件處理機制有兩種,一種是基于回調機制的,另一種是基于監聽接口的

Android平台中,每個View都有自己的處理事件的回調方法,開發人員可以通過重寫View中的這些回調方法來實作需要的響應事件。當某個事件沒有被任何一個View處理時,便會調用Activity中相應的回調方法

常用的回調方法:

  • onKeyDown 按下觸發
  • onKeyUp 彈起觸發
  • onTouchEvent 觸摸觸發
  • onTrackballEvent 軌迹球處理
  • onFocusChanged 焦點改變時觸發

代碼示例如下:

@Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        Log.d("GuiShou","onKeyUp");
        return super.onKeyUp(keyCode, event);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        Log.d("GuiShou","onKeyDown");
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d("GuiShou","onTouchEvent");
        return super.onTouchEvent(event);
    }
           

重寫三個響應事件

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-ahWkw4hA-1623033131158)(006 Android之Activity.assets/1622964287514.png)]

啟動app并産生相應的動作會列印日志

Activity之間的資料傳遞

Activity之間的資料傳遞分為以下幾步:

  1. 建立新的Activity
  2. 啟動Activity
  3. 在啟動之前傳遞資料

資料傳遞執行個體

006 Android之Activity

首先建立一個空的Activity檔案

006 Android之Activity

建立完成之後會産生一個新的layout檔案

然後在第一個Activity中編寫界面代碼

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tv1"
        android:textSize="20sp"
        android:text="第一個Activity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/btn1"
        android:text="啟動Activity"
        android:onClick="btnClick1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>
           

新增一個按鈕和響應事件,編寫代碼傳遞資料

public void btnClick1(View view) {
        //建立Intent對象
        Intent intent=new Intent();
        //設定類類型
        intent.setClass(this, Main2Activity.class);
        //設定傳遞的資料
        intent.putExtra("name","hello");
        //啟動Activity
        startActivity(intent);
    }
           

然後在另一個Activity的onCreate方法中接收資料

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

        //接收資料
        Intent intent=getIntent();
        String name=intent.getStringExtra("name");
        //顯示資料
        TextView textView=findViewById(R.id.tv2);
        textView.setText("傳遞的資料:"+name);
    }
           

實際效果如圖:

006 Android之Activity

Activity的生命周期

先上圖

006 Android之Activity
  1. 啟動Activity:系統會先調用onCreate方法,然後調用onStart方法,最後調用onResume,Activity進入運作狀态
  2. 當Activity被其他Activity覆寫或者被鎖屏,系統會調用onPause方法,暫停目前Activity的執行
  3. 目前Activity由被覆寫狀态回到前台或解鎖屏,系統會調用onResume方法,再次進入運作狀态
  4. 目前Activty轉到新的Activty界面或者按Home鍵回到主屏,自身退居背景,系統會先調用onPause方法,然後調用onStop方法,進入停滞狀态
  5. 使用者後退回到此Activty,系統會先調用onRestart方法,然後調用onStart方法,最後調用onResume方法,再次進入運作狀态
  6. 目前Activity處于被覆寫或者背景不可見狀态,即第二步和第四步,系統記憶體不足,殺死目前Activity,而後使用者退回目前Activity,再次調用onCreate方法、onStart方法、onResume方法,進入運作狀态。
  7. 使用者退出目前Activity:系統先調用onPause方法,然後調用onStop方法,最後調用onDestory方法,結束目前Activity。

下面看一個執行個體

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d("GuiShou","onCreate");
    }
    @Override
    protected void onRestart() {
        super.onRestart();
        Log.d("GuiShou","onRestart");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.d("GuiShou","onStart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d("GuiShou","onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d("GuiShou","onPause");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d("GuiShou","onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d("GuiShou","onDestroy");
    }
           

重寫MainActivity中的這幾個方法,并列印日志,接着啟動app

006 Android之Activity

程式會依次調用onCreate onStart和onResume三個方法

006 Android之Activity

然後點選回到首頁面,會調用onPause和onStop方法

006 Android之Activity

再次啟動程式,會調用onRestart onStart和onResume方法

了解了Activity的生命周期,作為一個開發者而言,應用程式在某種狀态下需要做一些備份和儲存,可以更好的去處理這些狀态;而作為逆向分析人員來說,就可以很清楚的知道這些函數執行的先後順序,進而明白應該先分析哪個方法,再分析哪個方法。

Activity聲明周期總結

Activity從建立到進入運作态所觸發的事件

從運作态到停止态所觸發的事件

從停止态到運作态所觸發的事件

從運作态到暫停态所觸發的事件

從暫停态到運作态所觸發的事件

Activity的任務棧

  • Android是通過一種任務棧的方式來管理Activity的
  • 當運作起來後就會開啟一條線程,線程中會運作一個任務棧,當Activity執行個體建立後就會放入任務棧
  • 一個Activity執行個體的狀态決定他在棧中的位置
  • 處于前台的Activity總是在棧的頂端,目前台的Activity因為異常或者其他原因被銷毀時,處于棧第二層的Activity将被激活,上浮到棧頂
  • 當新的Activity啟動入棧時,原Activity會被壓入到棧的第二層

Activity的啟動模式

Activity的啟動模式設定在Manifest檔案中,通過配置Activity的屬性

android:launchMode=

設定啟動模式

  1. standared模式(預設)
  2. singleTop模式
  3. singleTask模式
  4. singleInstance模式

預設啟動模式 standard

我們平時直接建立的Activity都是預設模式,這種模式的特點是:隻要你建立了Activity執行個體,一旦激活該Activity,則會向任務棧中加入新建立的執行個體,退出Activity則會在任務棧中銷毀該執行個體

如圖所示:

006 Android之Activity

棧頂複用模式 singleTop

這種模式會考慮目前要激活的Activity執行個體在任務棧中是否處于棧頂,如果處于棧頂則無需重新建立新的執行個體,會重用已存在的執行個體調用onNewIntent,否則會在任務棧中建立新的執行個體

006 Android之Activity

棧内複用模式 singleTask

如果任務棧中存在該模式的Activity,則把棧中該執行個體以上的Activity執行個體全部移除,調用該執行個體的onNewIntent方法重用該Activity,使該執行個體處于棧頂位置,否則就重新建立一個新的Activity執行個體

006 Android之Activity

對于那些及其耗費系統資源的Activity,我們可以考慮将其設為singleTask模式,減少資源耗費

全局唯一模式 singleInstance

這種啟動模式比較特殊,因為它會啟用一個新的棧結構,将Activity放置于這個新的結構中,并保證不再有其他的Activity執行個體進入

006 Android之Activity

四大元件之紐帶Intent

Intent概述

Andriod中的四大元件

  1. Activity(活動)—前台界面
  2. Service(服務)—背景服務
  3. Broadcast Receiver(廣播接收者)—回調函數
  4. Content Provider(内容提供商)—共享資料

Intent是元件與元件之間的紐帶,一個應用程式的三個核心元件——Activity Service Broadcast Receiver,都是通過intents的消息激活的

  • Activity:一個Intent對象傳遞startActivity()或startActivityForResult()去啟動一個活動或使一個已存在的活動去做新的事情
  • Service:一個Intent對象傳遞給startService()去初始化一個service或傳遞一個新的指令給正在運作的service。類似的,一個Intent可以傳遞給bindService()去建立調用元件和目标服務之間的連接配接
  • Broadcast Receiver:一個Intent對象傳遞給任何廣播方法(如sendBroadcast()),都将傳遞到所有感興趣的廣播接收者

Intent對象的組成

一個Intent對象包含對Intent有興趣的元件的資訊,有下面幾個部分

  1. 元件名稱(包名或類名)Component Class;通過setComponent()/setClass()或者setClassName()設定,通過getComponent()讀取
  2. 動作 Action;通過setAction()設定,通過getAction()擷取
  3. 資料 Data;通過setData()方法指定資料的URI,setType()指定MIME類型
  4. 種類 Category;通過addCategory()添加
  5. 附件資訊 Extras;通過putExtras()和getExtras()安裝和讀取

Intent過濾器(Intent Filter)

Intent Filter就是用來注冊Activity Service和Broadcast Receiver,具有能在某種資料上執行一個動作的能力

使用Intent Filter,應用程式元件告訴Android,它們能為其他程式的元件的動作請求提供服務,包括同一個程式的元件,本地的或第三方的應用程式

為了注冊一個應用程式元件為Intent處理者,在元件的manifest節點添加一個intent-filter标簽

常見的Intent Filter檢測

  1. 動作檢測,清單檔案中的元素以子元素列出動作
  2. 種類檢測,清單檔案中的元素以子元素列出動作
  3. 資料檢測,清單檔案中的元素以子元素列出動作

Intent對象的解析

Intent可以分為兩組:

  • 顯示Intent:通過名字指定目标元件,本身程式使用居多。之前的資料傳遞執行個體就是顯示Intent
  • 隐式Inyent:并不指定目标的名字,常用于激活其他程式中的元件

隐式方式啟動Activity執行個體:

首先在Manifest為要啟動的Activity新增一個action name屬性

<activity android:name=".Main2Activity">
            <intent-filter>
                <action android:name="com.example.a87321.action" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
           

然後在MainActivity中編寫代碼

public void btnClick4(View view) {
        //建立Intent對象
        Intent intent=new Intent();
       //設定資訊
        intent.setAction("com.example.a87321.action");
        //啟動Activity
        startActivity(intent);
    }
           

即可用隐式的方式啟動Activity