android之activity全面解析

本篇文章包括

概述

數據傳遞

生命週期

啓動模式

Activity 進入和退出動畫

概述

Activity是Android提供給開發者的一個組件,主要用於前臺界面的展示和交互。在android中,使用頻率最高,Android應用程序通常由多個Activity組成,幾乎所有Activity都與用戶交互。
activity工作流程

這裏有兩個幾乎所有Activity子類都會實現的方法:

onCreate(Bundle)
是你初始化Activity的地方。最重要的,這裏你經常會調用setContentView(int)並傳入一個佈局資源來定義你的UI,並且通過調用findViewById(int)得到UI中在編程時需要交互的組件。
onPause()
是處理用戶離開你Activity的地方。最重要的,所有用戶行爲導致產生的變化都應該在此節點提交(例如ContentProvider持有數據)。
爲了使用Context.startActivity(),所有Activity類型都必須在包的AndroidManifest.xml中存在對應的聲明。

Activity和AppcompatActivity

繼承AppCompatActivity的界面,界面會有一個默認的actionbar

public class MainActivity extends AppCompatActivity {  

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

如果繼承activity的話,該actionbar會消失。ActionBar向前兼容,出現在support v7裏,如果需要使用兼容版的actionbar,則繼承support v7提供的ActionBarActivity ,不過點進去ActionBarActivity從源碼看ActionBarActivity實際就是AppCompatActivity,就是帶有標題欄的Activity. 但是目前的v7包下並沒有ActionBarActivity,

所以現在最常用的還是AppcompaActivity,AppcompaActivity其實也是ActionBarActivity 修改而來。

AppcompaActivity相對於Activity的變化;

1 主界面帶有toolbar的標題欄;

2 theme主題只能用android:theme=”@style/AppTheme (appTheme主題或者其子類),而不能用android:style
否則會提示錯誤: Caused by: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.

activity實現全屏(去掉標題欄和狀態欄)

1、需要在setContentView方法調用之前設置。

requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);

2、 定義一個主題,在styles.xml裏面並引用。

<resources>
    <style name="Theme.NoTitle_FullScreen">
    	<item name="android:windowNoTitle">true</item>  
    	<item name="android:windowFullscreen">true</item>    
    </style>
</resources>

Intent 啓動Activity和傳遞數據

    1.intent.putExtra(key,value):
    //key一般是String,值爲 java八大基本數據類型及對應的數組,String及對應的數組,序列化 Serializable Parcelable的對象及對應的數組等
    2.intent.putExtras(bundle);
    3.intent.putExtra(key,bundle)
    
 Main2Activity(目標文件):
        1.intent.getXXXExtra(key)獲取值
        2.bundle=intent.getExtras()
        3.bundle=intent.getExtras(key)


   //顯式跳轉
   val intent= Intent(this,Main2Activity::class.java)
   startActivity(intent)

    //傳參
    val intent1= Intent(this,Main2Activity::class.java)
    intent1.putExtra("name","小明")
    startActivity(intent)

    //Main2Activity中
     val name=intent.getStringExtra("name")

    
    //bundle傳參
    val bundle=Bundle()
    bundle.putString("name","小明")
    val intent2= Intent(this,Main2Activity::class.java)
    intent2.putExtras(bundle)
    startActivity(intent)

    //Main2Activity中
    val bundle1=intent.extras
    val name1=bundle1.get("name")

startActivityForResult完成activity向第二個activity傳遞數據並且回傳數據。

1.使用startActivityForResult(intent,requestCode(大於等於0))方法激活目標Activity
2.在目標Activity 中調用setResult(resultCode,intent) 設置回傳到源Activity 的結果碼和意圖對象
3.在源Activity 中重寫onActivityResult(requestCode,resultCode,intent)方法得到目標Activity 回傳的數據

    //發起者中寫:
    val intent3= Intent(this,Main2Activity::class.java)
    intent3.putExtra("name","小明")
    startActivityForResult(intent3,100)

 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (resultCode==100&&resultCode==200){
        val name3=data?.getStringExtra("name")
      
    }

    //Main2Activity中
   // 收到數據
    val name2=intent.getStringExtra("name")

    //回傳數據
    val intent4= Intent(this,Main2Activity::class.java)
    intent4.putExtra("name","小紅")
    setResult(200,intent4)
}
}

傳遞對象時候,需要對對象進行序列化Serializable Parcelable

   class Student(id:Int,name:String,age:Int) :Serializable{   
    var id:Int=0
    var name:String=""
    var age:Int=0
}

  val intent5= Intent(this,Main2Activity::class.java)
    intent5.putExtra("student",Student(1,"小明",10))
    startActivity(intent)
   
    //Main2Activity中
   val student= intent.getSerializableExtra("student")

隱式啓動常用於不同應用之間的跳轉(例如打開支付寶微信的支付頁面),也可用於H5與native之間的交互。隱式啓動就是action,category和data的匹配,篇幅有限,請參考添加鏈接安卓Activity隱式啓動全面解析

Intent在傳遞數據時是有大小限制的,這裏官方並未詳細說明,不過通過實驗的方法可以測出數據應該被限制在1MB之內(1024KB)

activity生命週期

在這裏插入圖片描述

Activity的整個生命週期發生在onCreate()和onDestroy()之間,activity在此期間存在。

Activity的可見生命週期發生在onStart()和onStop()之間,activity在此期間狀態可見。

Activity的前景生命週期發生在調用onResume()和調用之間onPause(),activity在此期間處於屏幕最上層,用戶可以與之交互。

在這裏插入圖片描述

1、要保存用戶輸入數據,需要在onPause()中執行,而不是在onStop()和onDestroy()中.因爲如果離開當前activity onPause()一定被調用。

2、onSaveInstanceState()

onCreate就是Android提供給開發者用來對Activity實例對象中的成員做初始化的,

某些設備配置可能會在運行時更改(例如屏幕方向,鍵盤可用性和語言)。發生此類更改時,Android會重新創建正在運行的活動(系統調用onDestroy(),然後立即調用

onCreate()).處理此類重新啓動的最佳方法是使用onSaveInstanceState()和onRestoreInstanceState()(或onCreate())來保存和恢復Activity活動狀態

//用來保存用戶狀態信息onSaveInstanceState() 在Activity受破壞之前,系統會自動調用。系統會傳遞一個Bundle對象,您可以使用諸如putString()和putInt()之類的方

法將關於Activity的狀態信息保存爲名稱 - 值的鍵值對.
然後,如果系統終止您的應用程序進程,系統將重新創建活動並將其Bundle傳遞給Activity的onCreate()和

onRestoreInstanceState()。使用這些方法之一,您可以從中提取已保存的狀態Bundle並恢復活動狀態。如果沒有要恢復的狀態信息,則Bundle傳遞給您的是null

3、當dialog彈出來的時候,如果是單純是創建的dialog,Activity並不會執行生命週期的方法,但是如果是跳轉到一個不是全屏的Activity的話,當然就是按照正常的生

命週期來執行了,即onPasue()->onStop()。

4、設備橫豎屏切換的時候。

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

android:configChanges="orientation"時,切屏還是會重新調用各個生命週期,切橫、豎屏時只會執行一次;

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

tips:還有一點,非常重要,一個Android的變更細節!
當API >12時,需要加入screenSize屬性,否則屏幕切換時即使你設置了orientation系統也會重建Activity!

5、有時候activity界面如果有dialog經常會發生activity爲空,直接崩潰,這個時候可以加個判斷

if (!MainActivity.this.isDestroyed()) {
            new AlertDialog.Builder(MainActivity.this).setMessage("Show Dialog").show();
        }

Activity啓動模式:

Activity四種啓動模式的設定出於兩種目的:

複用機制,節省系統資源,這種情況主要發生在除Standard模式外的三種模式上,通過他們的名字前綴Single也可以看出,跟Java中的單例模式有類似的思想,避免太多的實例對象創建開銷。

根據用戶的交互行爲定義,因爲Activity最終的目的還是完成用戶在各種交互場景下的需求。

在android裏,有4種activity的啓動模式,分別爲:standard (默認) singleTop singleTask singleInstance

當應用運行起來後就會開啓一條線程,線程中會運行一個任務棧,當Activity實例創建後就會放入任務棧中。Activity啓動模式的設置在AndroidManifest.xml文件中,通過配置Activity的屬性android:launchMode=""設置。

1. Standared模式(默認)

我們平時直接創建的Activity都是這種模式的Activity,這種模式的Activity的特點是:只要你創建了Activity實例,一旦激活該Activity,則會向任務棧中加入新創建的實例,退出Activity則會在任務棧中銷燬該實例。

2. SingleTop 棧頂複用模式

棧頂模式,閱讀類app經常會使用。這種模式會考慮當前要激活的Activity實例在任務棧中是否正處於棧頂,如果處於棧頂則無需重新創建新的實例,會重用已存在的實例,否則會在任務棧中創建新的實例。standartd模式是activity的默認模式,大部分情況下,都應該使用這種模式,也就是在配置文件中什麼都不用做,當確實有特殊需求時,再考慮其他模式。

3. SingleTask 棧內複用模式

如果任務棧中存在該模式的Activity實例,則把棧中該實例以上的Activity實例全部移除,調用該實例的newInstance()方法重用該Activity,使該實例處於棧頂位置,否則就重新創建一個新的Activity實例。

4. SingleInstance模式

當該模式Activity實例在任務棧中創建後,只要該實例還在任務棧中,即只要激活的是該類型的Activity,都會通過調用實例的newInstance()方法重用該Activity,此時使用的都是同一個Activity實例,它都會處於任務棧的棧頂。此模式一般用於加載較慢的,比較耗性能且不需要每次都重新創建的Activity。

後臺堆棧

後臺堆棧指的是Activitys在後臺任務中的排列規則,按"後進先出"排列.

例如當前Activity啓動另一個Activity時,新Activity將被推到堆棧頂部並獲得焦點。之前的Activity仍在堆棧中,但已停止。當活動停止時,系統將保留其用戶界面的當前狀態。當用戶按下“ 返回” 按鈕時,當前Activity將從堆棧頂部彈出(活動被銷燬),之前的Activity將恢復(其UI的先前狀態將恢復)。堆棧中的活動永遠不會重新排列,只能在當前Activity啓動時從堆棧推送和彈出到堆棧中,並在用戶使用Back按鈕退出時彈出.因此,後臺堆棧作爲“後進先出”對象結構操作。

當此Activity的實例已經存在,並且此時的啓動模式爲SingleTask和SingleInstance,另外當這個實例位於棧頂且啓動模式爲SingleTop時也會觸發onNewInstent()。此方法會把activity帶到前臺。

activity進入退出動畫

淡入淡出爲例:
首先在res文件夾下建立anim文件夾,然後在裏面建立fade_in.xml和fade_out.xml兩個動畫資源

<?xml version="1.0" encoding="utf-8"?>  
<alpha xmlns:android="http://schemas.android.com/apk/res/android"  
    android:duration="500"  
    android:fromAlpha="0.0"  
    android:interpolator="@android:anim/accelerate_interpolator"  
    android:toAlpha="1.0" />


<?xml version="1.0" encoding="utf-8"?>  
<alpha xmlns:android="http://schemas.android.com/apk/res/android"  
    android:duration="1000"  
    android:fromAlpha="1.0"  
    android:interpolator="@android:anim/accelerate_interpolator"  
    android:toAlpha="0.0" /> 

然後在values文件夾下的styles.xml中的resources標籤內寫:

<style name="Anim_fade" parent="android:Theme.NoTitleBar">  
       <item name="android:windowAnimationStyle">@style/fade</item>  
   </style>  
  
   <style name="fade" parent="@android:style/Animation.Activity">  
       <item name="android:activityOpenEnterAnimation">@anim/fade_in</item>  
       <item name="android:activityOpenExitAnimation">@anim/fade_out</item>  
       <item name="android:activityCloseEnterAnimation">@anim/fade_in</item>  
       <item name="android:activityCloseExitAnimation">@anim/fade_out</item>  
   </style>

接下來在Mainfest中的activity中添加上android:theme="@style/Anim_fade"即可。
當然更簡單,更推薦的方法是在oncreate()裏面添加

  class Main2Activity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)
        overridePendingTransition(R.anim.fade_in,R.anim.fade_out)
    }

    override fun finish() {
        super.finish()
        overridePendingTransition(R.anim.fade_in,R.anim.fade_out)
    }
}

滑動動畫

slide_in_left:從左邊划進來:-100%p—>0
slide_in_right:從右邊划進來:100%p—>0
slide_out_left:從左邊劃出去:0—>-100%p
slide_out_right:從右邊劃出去:0—>100%p

R.anim.slide_in_left.xml

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate 
        android:duration="2000"
        android:fromXDelta="-100%p"
        android:toXDelta="0"/>

</set>

R.anim.slide_in_right.xml

R.anim.slide_out_left

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate 
        android:duration="2000"
        android:fromXDelta="0"
        android:toXDelta="-100%p"/>   
</set>

R.anim.slide_out_right

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate 
        android:duration="2000"
        android:fromXDelta="0"
        android:toXDelta="100%p"/>

</set>

R.anim.no_slide.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <alpha
        android:duration="300"
        android:fromAlpha="1"
        android:toAlpha="1" />
</set>

然後在values文件夾下的styles.xml中的resources標籤內寫:

<style name="Anim_translate" parent="android:Theme.NoTitleBar">  
       <item name="android:windowAnimationStyle">@style/translate</item>  
   </style>
   
    <style name="translate" parent="@android:style/Animation.Activity">  
       <item name="android:activityOpenEnterAnimation">@anim/slide_in_left</item>  
       <item name="android:activityOpenExitAnimation">@anim/slide_out_right</item>  
       <item name="android:activityCloseEnterAnimation">@anim/slide_in_right</item>  
       <item name="android:activityCloseExitAnimation">@anim/slide_out_left</item>  
   </style>

最後引用一下這個主題就好了
android:theme="@style/Anim_translate"

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章