Android四大組件——Activity

Activity做爲Android四大組件之一,也是其中最重要的一個組件。做爲一個與用戶交互的組件,咱們能夠把Activity比較成爲windows系統上的一個文件夾窗口,是一個與用戶交互的界面。再進一步說,當咱們拿起Android打開撥號功能,顯示出撥號盤的界面其實就是一個Activity;固然,能夠更大範圍的說,手機屏幕上顯示的任何界面都是一個個Activity。html

官方對Activity的描述前端

Activity是一個應用程序的組件,他在屏幕上提供了一個區域,容許用戶在上面作一些交互性的操做, 好比打電話,照相,發送郵件,或者顯示一個地圖!Activity能夠理解成一個繪製用戶界面的窗口, 而這個窗口能夠填滿整個屏幕,也可能比屏幕小或者浮動在其餘窗口的上方!android

從上面這段話,咱們能夠獲得如下信息:windows

  1. Activity用於顯示用戶界面,用戶經過Activity交互完成相關操做 
  2. 一個App容許有多個Activity

 相關連接:app

 

 

1.Activity的概念與Activity的生命週期圖:ide

注意事項:函數

1. onPause()和onStop()被調用的前提是: 打開了一個新的Activity!而前者是舊Activity還可見的狀態;後者是舊Activity已經不可見!
2. 另外,親測:AlertDialog和PopWindow是不會觸發上述兩個回調方法的~post

 

Activity的生命週期方法總共有七個。所謂生命週期,就是Activity在各個狀態轉變之間,系統會對其各個生命週期函數進行回調,也就讓咱們能夠根據業務需求,重寫各個生命週期方法來實現軟件在各個狀態的業務邏輯。this

啓動Activity到運行狀態: url

onCreate() -> onStart() -> onResume() -> 界面徹底顯示

運行狀態到暫停狀態:

  界面徹底顯示 -> onPause() -> 界面被部分遮蓋

暫停狀態到運行狀態:

  界面被部分遮蓋 -> onResume() -> 界面徹底顯示

運行狀態到中止狀態:

  界面徹底顯示 -> onPause() -> onStop() -> 界面徹底遮蓋

中止狀態到運行狀態:

  界面徹底遮蓋 -> onRestart() -> onStart() -> onResume() -> 界面徹底顯示

退出Activity:

  界面徹底顯示 -> onPause() -> onStop() -> 界面徹底遮蓋 -> onDestroy() -> Activity結束生命週期

PS:當系統內存緊張時,系統能夠將Activity釋放掉以獲取資源,優先釋放中止狀態的Activity,次之則是暫時狀態的Activity,而運行狀態的Acitivity通常不可能被強行釋放,除非極端缺少資源(這時候直接死機得了。。。),當Activity被釋放時,直接轉入消亡,須要注意一點的是onDestroy()並不會被執行,因此把數據保存放在onDestroy處理是不適當的,能夠在onSaveInstanceState()中對重要數據進行相應的處理。

Activity三種的狀態:

  • 運行狀態:當Activity處於屏幕最前端,此時Actiivity徹底顯示在用戶的界面中,並能獲取焦點時,能夠響應用戶的的觸摸屏幕等事件,此時爲運行狀態。用戶可見,可交互
  • 暫停狀態:當Activity被其餘Activity遮擋,可是仍然有部分可見,此時爲暫停狀態;當處於暫停狀態時,Activity仍然會更新UI,可是此時不能獲取焦點,即不會響應用戶觸摸、後退等事件。用戶可見,不可交互
  • 中止狀態:當Activity被另一個Activity徹底遮擋,此時爲中止狀態,中止狀態並不意味着Activity中止運行,而能夠理解爲轉入後臺運行。可是若是系統須要內存,會優先結束中止狀態的Activity釋放資源,因此在Activity轉入中止狀態時要對重要數據進行保存。用戶不可見,也不可交互

另外關於橫豎屏切割調用的生命週期以下:

橫屏->豎屏(調用一次生命週期)

  onPause() -> onStop() -> onDestroy() -> onCreate() -> onStart() -> onResume()

豎屏 -> 橫屏 (調用兩次生命週期)

若是不但願切換屏幕時調用生命週期方法,能夠有以下方法:

一、不設置Activity的android:configChanges時,切屏會從新調用各個生命週期,切橫屏時會執行一次,切豎屏時會執行兩次

二、設置Activity的android:configChanges="orientation"時,切屏仍是會從新調用各個生命週期,切橫、豎屏時只會執行一次

三、設置Activity的android:configChanges="orientation|keyboardHidden"時,切屏不會從新調用各個生命週期,只會執行onConfigurationChanged方法 

2.Activity/ActionBarActivity/AppCompatActivity的區別:

在開始講解建立Activity以前要說下這三個的一個區別: Activity就不用說啦,後面這兩個都是爲了低版本兼容而提出的提出來的,他們都在v7包下, ActionBarActivity已被廢棄,從名字就知道,ActionBar~,而在5.0後,被Google棄用了,如今用 ToolBar...而咱們如今在Android Studio建立一個Activity默認繼承的會是:AppCompatActivity! 固然你也能夠只寫Activity,不過AppCompatActivity給咱們提供了一些新的東西而已! 兩個選一個,Just you like~ 

3.Activity的建立流程

Android中的四大組件,只要你定義了,不管你用沒用,都要在AndroidManifest.xml對 這個組件進行聲明,否則運行時程序會直接退出,報ClassNotFindException... 

4.啓動一個Activity的幾種方式

 在Android中咱們能夠經過下面兩種方式來啓動一個新的Activity,注意這裏是怎麼啓動,而非啓動模式!!分爲顯示啓動和隱式啓動!

 1. 顯式啓動:經過包名來啓動,寫法以下:

①最多見的:

startActivity(new Intent(當前Act.this,要啓動的Act.class));
②經過Intent的ComponentName:
ComponentName cn = new ComponentName("當前Act的全限定類名","啓動Act的全限定類名") ; Intent intent = new Intent() ; intent.setComponent(cn) ; startActivity(intent) ;
初始化Intent時指定包名:
Intent intent = new Intent("android.intent.action.MAIN"); intent.setClassName("當前Act的全限定類名","啓動Act的全限定類名"); startActivity(intent);

2.隱式啓動:經過Intent-filter的Action,Category或data來實現 這個是經過Intent的 intent-filter**來實現的,這個Intent那章會詳細講解! 這裏知道個大概就能夠了!

3. 另外還有一個直接經過包名啓動apk的:

Intent intent = getPackageManager().getLaunchIntentForPackage ("apk第一個啓動的Activity的全限定類名") ; if(intent != null) startActivity(intent) ;

五、Activity間的數據傳遞:

 

 

  對於應用來講,單純從一個Activity啓動另一個Activity遠遠是不夠的,有時候須要比較的數據信息交流。android系統提供了不少種數據通訊的方法,天然也爲Activity之間的通訊提供了簡便的數據傳遞方法,參見下面代碼:

 

FirstActivity向OtherActivity傳送數據<data,"傳遞的數據">

1     Intent intent = new Intent(this, OtherActivity.class);
2         
3        intent.putExtra("data", "傳遞的數據");//data爲key
4 //        另一種方法,載入數據
5 //     Bundle bundle = new Bundle();
6 //     bundle.putString("data", "傳遞的數據");
7 //     intent.putExtras(bundle);
8         
9        startActivity(intent);

 

有兩種表示的方法,通常第一種方法運用的場景是傳輸少許並且簡單的數據;後一種方法則是傳輸較多而比較複雜的數據所用。可是從底層上說,其實第一種方法是後一種方法的封裝,它仍然會在intent內部建立一個bundle並把數據(如例子中的「傳遞的數據」)放入其中。

OtherActivity獲取傳送的數據<data,"傳遞的數據">

1         Intent intent = getIntent();
2 //        獲取方法
3         String data = intent.getStringExtra("data");//data的值爲「傳遞的數據」,由上個Activity傳入
4 //      另一種方法
5 //      Bundle bundle = intent.getExtras();
6 //      String data = bundle.getString("data");

 

獲取的方法通常是先取得intent攜帶的bundle,而後經過get方法獲取存儲在其中的數據;而前面的方法並無明確獲取bundle的代碼,由於intent.getStringExtra(key)在函數內部已是先獲取好bundle並把相應key的數據解析出來了,因此兩種方法本質上來講是相同的,可是若是大量數據建議用後一種方法,由於從bundle中獲取數據比從intent中獲取數據效率有所提升,比較移動時代,效率是一個很是須要重視的東東。。

 FristActivity啓動OtherActivity並在其結束時獲取OtherActivity返回的數據

若是業務須要啓動另外一個Activity後返回數據給原來的Activity,在啓動Activity是否是調用startActivity(intent),而是應該調用startActivityForResult(intent, requestCode),requestCode是一個給啓動的Activity的標識碼,是一個正整數的值,在有多個啓動的Activity時能夠經過不一樣的標識碼來表示Activity返回的數據並進行不一樣的處理。在FristActivity中處理返回數據是在 onActivityResult(requestCode, resultCode, data)中處理,而第一個參數requestCode則是啓動時輸入的標識碼。參見代碼

1  Intent intent = new Intent(this, OtherActivity.class);
2  startActivityForResult(intent, 0);//設置標識碼爲0

 

這是啓動Activity的代碼,可是咱們要對於返回的數據,還須要在FristActivity中重寫onActivityResult(requestCode, resultCode, data)

1 @Override
2 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
3   super.onActivityResult(requestCode, resultCode, data);
4   if(requestCode == 0){//根據requestCode的數值確實是哪一個Activity返回的bundle
5     Bundle bundle = data.getExtras();
6     String getdata = bundle.getString("name");
7   }
8 } 
複製代碼

而後在啓動的OtherActivity中重寫返回數據的方法

    Intent intent = new Intent();
    intent.putExtra("name", "返回的數據");
    setResult(1, intent);//設置須要返回數據的intent
    finish();//結束當前的activity    

 

通常setResult後須要調用finish()結束當前的Activity,此時纔會將數據返回到FristActivity,數據返回也就是onActivityResult調用的時間在finish以前調用。

 

下面是實現具體代碼:

MainActivity 

package cn.com.qiang.buttondemo;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        Button button1 = (Button) findViewById(R.id.button1);
        
        button1.setOnClickListener(new MyListon());
    }
    
    class MyListon implements OnClickListener{
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
        Intent intent = new Intent();
        intent.setClass(MainActivity.this,SecondActivity.class);
        intent.putExtra("key", "給你發個美女圖片");
        startActivity(intent);
        }
    }   
}

SecondActivity

package cn.com.qiang.buttondemo;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;

public class SecondActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState){
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
    
        Intent intent = getIntent();
        String s = intent.getStringExtra("key");
        TextView tv = (TextView) findViewById(R.id.tv);
        tv.setText(s);
    }
}
相關文章
相關標籤/搜索