Activity你应该知道的一切
2016-12-22 09:36
405 查看
Activity简介
Activity是一种展示型组件,用于向用户直接展示一个界面,并且可以接受用户的输入信息从而进行交互。Activity是最重要的一组组件,对用户来说,Activity是一个Android用户的全部,因为其他三大组件对于用户来说都是不可感知的。Activity的启动由Intent触发,其中Intent可以分为显示Intent和隐式Intent。Activity是具有生命周期的。一个Acticity组件可以有不同的启动模式,不同的启动模式具有不同的效果。Intent可以用于Activity之间进行数据的传递。Activity组件是可以停止的,在实际开发过程中可以通过Activity的finish方法来结束Activity的运行。Activity扮演的是一种前台界面的角色Activity的生命周期
首先来看一张Activity的生命周期图:![](http://upload-images.jianshu.io/upload_images/2965516-b937352bf01de22f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
正常情况下的生命周期分析
(1)第一次启动一个Activity,回调方法:onCreate—>onStart—>onResume![](http://upload-images.jianshu.io/upload_images/2965516-da2bc210bf9f30e3.gif?imageMogr2/auto-orient/strip)
(2)当用户按住Home键的时候,回调如下:onPause->onStop
![](http://upload-images.jianshu.io/upload_images/2965516-fb64c4074a9b5ceb.gif?imageMogr2/auto-orient/strip)
(3)当用户再次返回到原Activity的时候,回调方法如下:
onRestart->onStart->onResume
![](http://upload-images.jianshu.io/upload_images/2965516-1c4eff9b2fb396a0.gif?imageMogr2/auto-orient/strip)
(4)当用户按back键回退时,回调方法如下:onPause->onStop->onDestroy
![](http://upload-images.jianshu.io/upload_images/2965516-d66e8ef15928b4c5.gif?imageMogr2/auto-orient/strip)
异常情况下的生命周期分析
![](http://upload-images.jianshu.io/upload_images/2965516-967c845bd6fdc862.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
(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会被杀死并重新创建,运行结果截图如下:
![](http://upload-images.jianshu.io/upload_images/2965516-3126fcaa31d1d1f1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
系统配置中内容很多,如何当某项内容发生改变后,我们不想系统重新创建Activity,可以给Activity指定configChanges属性,比如如果不想让屏幕旋转时重新创建,可以给onfigChanges属性添加orientation这个值。
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中的四种启动模式:standard、singleTop、singleTask、singleInstance
- standard:标准模式,也是默认的启动模式
每次启动一个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命令查看任务栈情况
![](http://upload-images.jianshu.io/upload_images/2965516-4f3cc14b7e616c56.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
可以看出此时只有一个任务栈,任务栈为当前包名,任务栈中有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的时候,不会重新创建,此时的任务栈中应该只有一个实例
看运行截图:
![](http://upload-images.jianshu.io/upload_images/2965516-9c643bdfea0d6bc2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
只有一个任务栈,任务栈中只有一个实例
singleTask:栈内复用模式
当一个具有singleTask模式的Activity请求启动后,比如说Activity A,系统首先会寻找是否存在A想要的任务栈,如果不存在A所需的任务栈,就会重新创建一个任务栈,然后创建A的实例并把A放入任务栈中。如果存在A所需的任务栈,这是要看A是否在栈中有实例存在,如果存在,就把A调到栈顶并调用它的onNewIntent方法,如果不存在,就创建A的实例并把A压入栈中。
<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实例已经存在,系统就会把MainActivity实例调到栈顶,并两次调用它的onNewIntent方法
看运行截图:
![](http://upload-images.jianshu.io/upload_images/2965516-9c643bdfea0d6bc2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
两次调用onNewIntent方法:
![](http://upload-images.jianshu.io/upload_images/2965516-129f130b7bf7b82d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
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=”true”。
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>
action的匹配规则
要求Intent中的action存在且必须和过滤规则中的其中一个相同
category的匹配规则
可以不设置,要设置的话,每一个都必须和过滤规则中的任一个相同
data的匹配规则
和action的匹配规则类似,如果过滤规则中定义了data,那么Intent中必须要定义可匹配的data
下面给出匹配规则
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的基础知识的总结
CSDN博客:http://blog.csdn.net/u014005316
Github:https://github.com/zeke123
掘金:https://gold.xitu.io/user/5740329671cfe4006c391e1d
简书:http://www.jianshu.com/users/002601150b0b/latest_articles
相关文章推荐
- android activity 应该知道的一切(完整篇)
- android activity 应该知道的一切
- 关于Activity你应该知道的一切
- Fragment 你应该知道的一切
- Android Fragment 你应该知道的一切
- 第一次使用Android Studio时你应该知道的一切配置
- Android Fragment 你应该知道的一切
- fragment简介及你应该知道的一切
- 第一次使用Android Studio时你应该知道的一切配置(三):gradle项目构建
- Android Fragment 你应该知道的一切
- Fragment---Fragment你应该知道的一切
- Android Fragment 你应该知道的一切
- Android Fragment 你应该知道的一切
- 关于Android内存优化你应该知道的一切
- Android Fragment 你应该知道的一切
- 第一次使用Android Studio时你应该知道的一切配置
- Android异步之Asynctask与Handler你所应该知道的一切
- 第一次使用Android Studio时你应该知道的一切配置
- 属性动画-Property Animation之ViewPropertyAnimator 你应该知道的一切