Activity簡介
Activity是一種展示型組件,用於向用戶直接展示一個界面,並且可以接受用戶的輸入信息從而進行交互.Activity是最重要的一組組件,對用戶來說,Activity是一個Android的用戶的全部,因為其他三大組件對於用戶來說都是不可感知的.Activity的啟動由Intent觸發,其中Intent可以分為顯示Intent和隱式Intent.Activity是具有生命週期的。一個Acticity組件可以有不同的啟動模式,不同的啟動模式具有不同的效果.Intent可以用於Activity之間進行數據的傳遞.Activity組件是可以停止的,在實際開發過程中可以通過活性的光潔度方法來結束Activity的運行.Activity扮演的是一種前台界面的角色
Activity的生命週期
首先來看一張Activity的生命週期圖:

正常情況下的生命週期分析
(1)第一次啟動一個Activity,回調方法:onCreate-> onStart->的onResume

(2)當用戶按住主頁鍵的時候,回調如下:onPause->的onStop

(3)當用戶再次返回到原Activity的時候,回調方法如下:
onRestart-> onStart-> onResume

(4)當用戶按背面鍵回退時,回調方法如下:onPause-> onStop->的onDestroy

異常情況下的生命週期分析

(1)系統配置發生改變導致Activity被殺死並重新創建
比如說,當橫豎屏切換的時候,Activity就會被銷毀並重新創建,當然我們也可以阻止系統重新創建Activity。當系統配置發生變化是,在的onStop之前會調用的onSaveInstanceState方法來保存當前Activity的狀態。當Activity被重新創建後,系統會調用onRestoreInstanceState方法來恢復之前保存的狀態,這個方法在調用onStart方法之後執行。
看代碼:
- package note.com.chapter_01;
- import android.app.Activity;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.View;
- import android.widget.Button;
- import butterknife.ButterKnife;
- import butterknife.InjectView;
- /**
- * Created by zhoujian on 16/9/11.
- */
- public class SecondActivity extends Activity {
- private static final String TAG = "SecondActivity";
- @InjectView(R.id.bt_back)
- Button mBtBack;
- private String mName;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_second);
- ButterKnife.inject(this);
- Log.e(TAG, "onCreate()方法执行了");
- if (savedInstanceState != null) {
- mName = savedInstanceState.getString("name");
- Log.e(TAG, "onCreate=" + mName);
- }
- clickEvent();
- }
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putString("name", "周建");
- Log.e(TAG,"onSaveInstanceState方法执行了");
- }
- @Override
- protected void onRestoreInstanceState(Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
- //快捷键:option+command+f 快速提取变量
- String mName = savedInstanceState.getString("name");
- Log.e(TAG, "onRestoreInstanceState=" + mName);
- }
- private void clickEvent() {
- mBtBack.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- finish();
- }
- });
- }
- @Override
- protected void onRestart() {
- super.onRestart();
- Log.e(TAG, "onRestart()方法执行了");
- }
- @Override
- protected void onStart() {
- super.onStart();
- Log.e(TAG, "onStart()方法执行了");
- }
- @Override
- protected void onResume() {
- super.onResume();
- Log.e(TAG, "onResume()方法执行了");
- }
- @Override
- protected void onPause() {
- super.onPause();
- Log.e(TAG, "onPause()方法执行了");
- }
- @Override
- protected void onStop() {
- super.onStop();
- Log.e(TAG, "onStop()方法执行了");
- }
- @Override
- protected void onDestroy() {
- super.onDestroy();
- Log.e(TAG, "onDestroy()方法执行了");
- }
- }
複製代碼
當橫豎屏切換的時候,Activity會被殺死並重新創建,運行結果截圖如下:

系統配置中內容很多,如何當某項內容發生改變後,我們不想系統重新創建Activity,可以給Activity指定configChanges屬性,比如如果不想讓屏幕旋轉時重新創建,可以給onfigChanges屬性添加定位這個值。
- android:configChanges="orientation"
複製代碼
android:configChanges的屬性有很多,具體讀者可以查閱相關文檔。
- android:configChanges="orientation|mcc|mnc|locale|touchscreen|keyboard
- |keyboardHidden|navigation|screenLayout|fontScale|uiMode|screenSize
- |smallestScreenSize|layoutDirection">
複製代碼
(2)資源內存不足導致低優先級的Activity被殺死,導致Ativity被銷毀並重新創建
優先級從高到低如下:
正在和用戶交互的Activity優先級最高。
可見但非前台的Activity,比如Activity中彈出了一個對話框,導致Activity可見但是位於後台無法和用戶交互。
已經被暫停的Activity,優先級最低。
Activity的啟動模式
默認情況下,當我們多次啟動同一個Activity的時候,系統會創建多個實例並把它們一一放入任務棧中。任務棧是一種“先進後出”的棧結構
.Android中的四種啟動模式:標準,singleTop,singleTask,singleInstance
標準:標準模式,也是默認的啟動模式
。每次啟動一個Activity都會重新創建一個實例,不管這個實例是否存在在這種模式下,誰啟動了這個Activity,這個Activity就運行在啟動它的那個Activity的任務棧中。
- <activity
- android:name=".MainActivity"
- android:launchMode="standard">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
複製代碼
比如說連續兩次啟動MainActivity,然後執行adb shell dumpsys activity命令查看任務棧情況

可以看出此時只有一個任務棧,任務棧為當前包名,任務棧中有3個MainActivity(原本的一個MainActivity和啟動兩次)
singleTop:棧頂复用模式
。如果新的Activity的實例已經存在並且位於棧頂,那麼此Activity被不會重新創建³³
如果新的Activity的實例已經存在但不是位於棧頂,那麼此Activity仍然會重新創建。
- <activity
- android:name=".MainActivity"
- android:launchMode="singleTop">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
複製代碼
比如說連續兩次啟動MainActivity,然後執行adb shell dumpsys activity命令查看任務棧情況
因為MainActivity已經位於棧頂了,兩次啟動MainActivity的時候,不會重新創建,的此時棧任務中應該只有一個實例
看運行應用說明教學:

只有一個任務棧,任務棧中只有一個實例
singleTask:棧內復用模式
當一個具有singleTask模式的Activity請求啟動後,比如說ActivityA,系統首先會尋找是否存在A想要的任務棧,如果不存在A所需的任務棧,就會重新創建一個任務棧,然後創建甲的實例並把甲放入任務棧中。如果存在一個所需的任務棧,這是要看甲是否在棧中有實例存在,如果存在,就把甲調到棧頂並調用它的onNewIntent方法,如果不存在,就創建一個的實例並把一個壓入棧中。
- <activity
- android:name=".MainActivity"
- android:launchMode="singleTask">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
複製代碼
比如說連續兩次啟動MainActivity,然後執行adb shell dumpsys activity命令查看任務棧情況
因為MainActivity實例調經棧頂,並且兩次調用它的onNewIntent方法
看運行截圖:

兩次調用onNewIntent方法:

singleInstance:實例單模式
除具有singleTask模式的所有特徵外,singleInstance模式的Activity只能單獨位於一個任務棧中。
指定啟動模式
有兩種方式指定啟動模式,方式第二種優先級高於第一種
第一種的英文在清單文件為Activity指定啟動模式
- <activity
- android:name=".MainActivity"
- android:launchMode="singleTask">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
複製代碼
第二種是通過給Intent設置標誌位來為Activity指定啟動模式
- Intent mIntent =new Intent(MainActivity.this,MainActivity.class);
- mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(mIntent);
複製代碼
Activity的Flags
FLAG_ACTIVITY_NEW_TASK
作用是為Activity指定singleTask啟動模式,和在清單文件中指定效果相同。
FLAG_ACTIVITY_SINGLE_TOP
作用是為Activity指定singleTop啟動模式,和在清單文件中指定效果相同。
FLAG_ACTIVITY_CLEAR_TOP
具有此標記位的Activity,當它啟動時,在同一個任務棧中所有位於它上面的Activity都要出棧。
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
具有這個標記位的Activity不會出現在歷史Activity的列表中,等同於指定的android:excludeFromRecents =“真”。
Activity的顯示調用和隱式調用
顯示調用:指定明確被啟動對象的組件信息
隱式調用:不需要指定組件信息,隱式調用需要Intent能夠匹配目標組件的IntentFilter中所設置的過濾信息,如果不匹配則無法調用目標Activity
- <activity android:name=".SecondActivity">
- <intent-filter>
- <action android:name="com.zhoujian.define"/>
- <action android:name="com.zhoujian.start"/>
- <category android:name="com.zhoujian.text"/>
- <category android:name="com.zhoujian.cool"/>
- <category android:name="android.intent.category.DEFAULT"/>
- <data android:mimeType="text/plain"/>
-
- </intent-filter>
- </activity>
複製代碼
動作匹配的規則
要求意向中的作用存在且必須和過濾規則中的其中一個相同
類別匹配的規則
可以不設置,要設置的話,每一個都必須和過濾規則中的任一個相同
數據匹配的規則
狀語從句:行動的匹配規則類似,如果過濾規則中定義了數據,那麼意向中必須要定義可匹配的數據
下面給出匹配規則
- Intent mIntent = new Intent();
- mIntent.setAction("com.zhoujian.define");
- mIntent.addCategory("com.zhoujian.text");
- mIntent.addCategory("com.zhoujian.cool");
- mIntent.setDataAndType(Uri.parse("file://abc"),"text/plain");
- startActivity(mIntent);
複製代碼
Intent在Activity間傳遞數據
Intent傳遞簡單數據
在原Activity發送數據
- Intent intent = new Intent(MainActivity.this,SecondActivity.class);
- Bundle bundle = new Bundle();
- bundle.putString("name","周建");
- bundle.putInt("age",25);
- intent.putExtras(bundle);
- startActivity(intent);
複製代碼
在目標的Activity接受數據
- Intent intent = getIntent();
- bundle = intent.getExtras();
- String mName = bundle.getString("name");
- int mAge = bundle.getInt("age");
- Log.d(TAG, "姓名:"+mName+",年龄:"+mAge);
複製代碼
Intent傳遞的JavaBean
實現Serializable接口接口
- package note.com.chapter_01;
- import java.io.Serializable;
- /**
- * Created by zhoujian on 2016/12/21.
- */
- public class Person implements Serializable
- {
- private static final long serialVersionUID = 1L;
- private int age;
- private String name;
- public int getAge()
- {
- return age;
- }
- public void setAge(int age)
- {
- this.age = age;
- }
- public String getName()
- {
- return name;
- }
- public void setName(String name)
- {
- this.name = name;
- }
- @Override
- public String toString()
- {
- return "Person{" +"age=" + age + ", name='" + name + '\'' + '}';
- }
- }
複製代碼
在原Activity發送數據
- Person person= new Person();
- person.setName("周建");
- person.setAge(25);
- Intent intent = new Intent(MainActivity.this,SecondActivity.class);
- intent.putExtra("person",person);
- startActivity(intent);
複製代碼
在目標的Activity接受數據
- Intent intent = getIntent();
- Person mPerson = (Person)intent.getSerializableExtra("person");
- Log.d(TAG, mPerson.toString());
複製代碼
實現Parcelable接口
- package note.com.chapter_01;
- import android.os.Parcel;
- import android.os.Parcelable;
- /**
- * Created by zhoujian on 2016/12/21.
- */
- public class User implements Parcelable
- {
- private int age;
- private String name;
- public User()
- {
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- @Override
- public int describeContents() {
- return 0;
- }
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(this.age);
- dest.writeString(this.name);
- }
- protected User(Parcel in) {
- this.age = in.readInt();
- this.name = in.readString();
- }
- public static final Creator<User> CREATOR = new Creator<User>()
- {
- @Override
- public User createFromParcel(Parcel source)
- {
- return new User(source);
- }
- @Override
- public User[] newArray(int size)
- {
- return new User[size];
- }
- };
- @Override
- public String toString()
- {
- return "User{" + "age=" + age + ", name='" + name + '\'' + '}';
- }
- }
複製代碼
在原Activity發送數據
- User user = new User();
- user.setAge(25);
- user.setName("周建");
- Intent intent = new Intent(MainActivity.this,SecondActivity.class);
- intent.putExtra("user",user);
- startActivity(intent);
複製代碼
在目標的Activity接受數據
- Intent intent = getIntent();
- User mUser = (User) intent.getParcelableExtra("user");
- Log.d(TAG, mUser.toString());
複製代碼
Intent傳遞集合
在原Activity發送數據
- ArrayList<Person> personArrayList = new ArrayList<Person>();
- Person Aperson= new Person();
- Aperson.setName("周建");
- Aperson.setAge(25);
- personArrayList.add(Aperson);
- Person Bperson= new Person();
- Bperson.setName("zhoujian");
- Bperson.setAge(28);
- personArrayList.add(Bperson);
- Intent intent = new Intent(MainActivity.this,SecondActivity.class);
- intent.putExtra("personArrayList",(Serializable)personArrayList);
- startActivity(intent);
複製代碼
在目標的Activity接受數據
- Intent intent = getIntent();
- ArrayList<Person> mList = (ArrayList<Person>) intent.getSerializableExtra("personArrayList");
- Log.d(TAG, mList.toString());
複製代碼
onActivityResult
MainActivity.java
- private void clickEvent() {
- mButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- Intent intent = new Intent(MainActivity.this, SecondActivity.class);
- //requestCode
- startActivityForResult(intent, INTENT_FLAG);
- }
- });
- }
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (resultCode == RESULT_OK)
- {
- switch (requestCode)
- {
- case INTENT_FLAG:
- String result = data.getStringExtra("msg");
- Toast.makeText(this, result, Toast.LENGTH_SHORT).show();
- break;
- }
- }
- }
複製代碼
SecondActivity.java
- private void clickEvent() {
- mBtBack.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- Intent intent = new Intent();
- intent.putExtra("msg","我来自第二个界面");
- setResult(RESULT_OK,intent);
- finish();
- }
- });
- }
複製代碼
以上就是有關Activity的基礎知識的總結
|