生命周期
官网上的生命周期图:
- onCreate: Activity正在创建,生命周期的第一个方法。在此方法中做一些初始化工作(setContentView加载界面布局,加载基本数据)
- onStart: Activity 正在启动,已经可见,但在后台(没有获得焦点)
- onResume: Activity获得焦点出现在前台可以交互
- onPause: Activity 正在停止,可做一些数据存储,停止动画...
- onStop: Activity 停止,不可见
- onDestory: Activity 销毁,进行资源回收
基本函数
public void onCreate(Bundle savedInstanceState);
public void onStart();
public void onRestart();
public void onActivityResult(int requestCode, int resultCode, Intent data);
public void onResume();
public void onPause();
public void onStop();
public void onDestroy();
public void attach(Activity proxyActivity, DLPluginPackage pluginPackage);
public void onSaveInstanceState(Bundle outState);
public void onNewIntent(Intent intent);
public void onRestoreInstanceState(Bundle savedInstanceState);
public boolean onTouchEvent(MotionEvent event);
public boolean onKeyUp(int keyCode, KeyEvent event);
public void onWindowAttributesChanged(LayoutParams params);
public void onWindowFocusChanged(boolean hasFocus);
public void onBackPressed();
public boolean onCreateOptionsMenu(Menu menu);
public boolean onOptionsItemSelected(MenuItem item);
- onRestart:Activity 正在重现启动,是当前Activity从不可见到可见状态会触发
- onActivityResult: 在Activity中得到新打开Activity关闭后返回的数据
特殊情况下触发(横竖屏切换,资源不足被杀)
- onSaveInstanceState:Activity被销毁,调用此方法保存当前状态,在onStop之前调用
- onRestoreInstanceState:Activity 被重启调用,通过Bundle传递保存的数据,在onStart 之后调用
- onNewIntent
- onTouchEvent 触摸屏幕时调用,可以获取手势的位置
- onKeyUp 键盘事件,点击来手机按键
- onWindowAttributesChanged
- onWindowFocusChanged
- onBackPressed 返回键点击
- onCreateOptionsMenu 加载菜单布局
- onOptionsItemSelected 响应菜单选项
对话框模式
<activity
android:name=".TAccountActivity"
android:theme="@android:style/Theme.Translucent"
android:configChanges="fontScale|orientation|keyboardHidden|locale|navigation|screenSize|uiMode"
android:screenOrientation="portrait"
/>
布局文件设置在父布局的中间,动态添加一个fragment
<FrameLayout
android:id="@+id/account_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
/>
启动模式
Standared(默认):standard是默认的启动模式,即如果不指定launchMode属性,则自动就会使用这种启动模式。这种启动模式表示每次启动该Activity时系统都会为创建一个新的实例,并且总会把它放入到当前的任务当中。声明成这种启动模式的Activity可以被实例化多次,一个任务当中也可以包含多个这种Activity的实例。
SingleTop:这种启动模式表示,如果要启动的这个Activity在当前任务中已经存在了,并且还处于栈顶的位置,那么系统就不会再去创建一个该Activity的实例,而是调用栈顶Activity的onNewIntent()方法。声明成这种启动模式的Activity也可以被实例化多次,一个任务当中也可以包含多个这种Activity的实例。
举个例子来讲,一个任务的返回栈中有A、B、C、D四个Activity,其中A在最底端,D在最顶端。这个时候如果我们要求再启动一次D,并且D的启动模式是"standard",那么系统就会再创建一个D的实例放入到返回栈中,此时栈内元素为:A-B-C-D-D。而如果D的启动模式是"singleTop"的话,由于D已经是在栈顶了,那么系统就不会再创建一个D的实例,而是直接调用D Activity的onNewIntent()方法,此时栈内元素仍然为:A-B-C-D。SingleTask:这种启动模式表示,系统会创建一个新的任务,并将启动的Activity放入这个新任务的栈底位置。但是,如果现有任务当中已经存在一个该Activity的实例了,那么系统就不会再创建一次它的实例,而是会直接调用它的onNewIntent()方法。声明成这种启动模式的Activity,在同一个任务当中只会存在一个实例。注意这里我们所说的启动Activity,都指的是启动其它应用程序中的Activity,因为"singleTask"模式在默认情况下只有启动其它程序的Activity才会创建一个新的任务,启动自己程序中的Activity还是会使用相同的任务
SingleInstance:这种启动模式和"singleTask"有点相似,只不过系统不会向声明成"singleInstance"的Activity所在的任务当中再添加其它Activity。也就是说,这种Activity所在的任务中始终只会有一个Activity,通过这个Activity再打开的其它Activity也会被放入到别的任务当中。
再举一个例子,Android系统内置的浏览器程序声明自己浏览网页的Activity始终应该在一个独立的任务当中打开,也就是通过在<activity>元素中设置"singleTask"启动模式来实现的。这意味着,当你的程序准备去打开Android内置浏览器的时候,新打开的Activity并不会放入到你当前的任务中,而是会启动一个新的任务。而如果浏览器程序在后台已经存在一个任务了,则会把这个任务切换到前台。
其实不管是Activity在一个新任务当中启动,还是在当前任务中启动,返回键永远都会把我们带回到之前的一个Activity中的。但是有一种情况是比较特殊的,就是如果Activity指定了启动模式是"singleTask",并且启动的是另外一个应用程序中的Activity,这个时候当发现该Activity正好处于一个后台任务当中的话,就会直接将这整个后台任务一起切换到前台
启动方式
显式
需要知道SecondActivity的存在
Intent intent=new Intent(MainActivity.this, SecondActivity.class);
//intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent);
使用Intent flags
除了使用manifest文件之外,你也可以在调用startActivity()方法的时候,为Intent加入一个flag来改变Activity与任务的关联方式
FLAG_ACTIVITY_NEW_TASK
设置了这个flag,新启动Activity就会被放置到一个新的任务当中(与"singleTask"有点类似,但不完全一样),当然这里讨论的仍然还是启动其它程序中的Activity。这个flag的作用通常是模拟一种Launcher的行为,即列出一推可以启动的东西,但启动的每一个Activity都是在运行在自己独立的任务当中的。FLAG_ACTIVITY_SINGLE_TOP
设置了这个flag,如果要启动的Activity在当前任务中已经存在了,并且还处于栈顶的位置,那么就不会再次创建这个Activity的实例,而是直接调用它的onNewIntent()方法。这种flag和在launchMode中指定"singleTop"模式所实现的效果是一样的。FLAG_ACTIVITY_CLEAR_TOP
设置了这个flag,如果要启动的Activity在当前任务中已经存在了,就不会再次创建这个Activity的实例,而是会把这个Activity之上的所有Activity全部关闭掉。比如说,一个任务当中有A、B、C、D四个Activity,然后D调用了startActivity()方法来启动B,并将flag指定成FLAG_ACTIVITY_CLEAR_TOP,那么此时C和D就会被关闭掉,现在返回栈中就只剩下A和B了。
那么此时Activity B会接收到这个启动它的Intent,你可以决定是让Activity B调用onNewIntent()方法(不会创建新的实例),还是将Activity B销毁掉并重新创建实例。如果Activity B没有在manifest中指定任何启动模式(也就是"standard"模式),并且Intent中也没有加入一个FLAG_ACTIVITY_SINGLE_TOP flag,那么此时Activity B就会销毁掉,然后重新创建实例。而如果Activity B在manifest中指定了任何一种启动模式,或者是在Intent中加入了一个FLAG_ACTIVITY_SINGLE_TOP flag,那么就会调用Activity B的onNewIntent()方法。
FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_NEW_TASK结合在一起使用也会有比较好的效果,比如可以将一个后台运行的任务切换到前台,并把目标Activity之上的其它Activity全部关闭掉。这个功能在某些情况下非常有用,比如说从通知栏启动Activity的时候。FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS Activity不会出现在历史activity的列表中,等价于 xml 中配置
android:excludeFromRecents="treu"
隐式
隐式启动不同之处在于我们并不需要像Intent(MainActivity.this, SecondActivity.class)这样传参数然后再Start另一个Activity.我们需要在intent添加过滤器intentfilter。
<activity
android:name="com.example.android.tst.SecondActivity"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="com.example.android.tst.SecondActivity"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Intent intent=new Intent("com.example.android.tst.SecondActivity");
startActivity(intent);
- action 匹配,字符串匹配(系统内置,自定义),区分大小写。一个过滤规则中可以有多个action,只要任何一个匹配成功即可
- category 匹配,也是一个字符串,(系统内置,自定义),每一个都需要匹配成功,系统会自动加上
<category android:name="android.intent.category.DEFAULT" /> 的匹配 - data 匹配, scheme, host, port, path, pathPrefix, pathPattern 是用来匹配 Intent 中的 Data Uri 的。具体规则如下: scheme://host:port/path or pathPrefix or pathPattern
setType 调用后设置 mimeType,然后将 data 置为 null;
setData 调用后设置 data,然后将 mimeType 置为 null;
setDataAndType 调用后才会同时设置 data 与 mimeType。
-
示例,短信中包含一个连接,可以直接打开应用
<intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:host="www.aaa.com" android:pathPrefix="/bbb" android:scheme="http" /> <data android:host="www.aaa.com" android:pathPrefix="/ccc" android:scheme="http" /> </intent-filter>
清空返回栈
如果用户将任务切换到后台之后过了很长一段时间,系统会将这个任务中除了最底层的那个Activity之外的其它所有Activity全部清除掉。当用户重新回到这个任务的时候,最底层的那个Activity将得到恢复。这个是系统默认的行为,因为既然过了这么长的一段时间,用户很有可能早就忘记了当时正在做什么,那么重新回到这个任务的时候,基本上应该是要去做点新的事情了。
当然,既然说是默认的行为,那就说明我们肯定是有办法来改变的,在<activity>元素中设置以下几种属性就可以改变系统这一默认行为:
- alwaysRetainTaskState
如果将最底层的那个Activity的这个属性设置为true,那么上面所描述的默认行为就将不会发生,任务中所有的Activity即使过了很长一段时间之后仍然会被继续保留。 - clearTaskOnLaunch
如果将最底层的那个Activity的这个属性设置为true,那么只要用户离开了当前任务,再次返回的时候就会将最底层Activity之上的所有其它Activity全部清除掉。简单来讲,就是一种和alwaysRetainTaskState完全相反的工作模式,它保证每次返回任务的时候都会是一种初始化状态,即使用户仅仅离开了很短的一段时间。 - finishOnTaskLaunch
这个属性和clearTaskOnLaunch是比较类似的,不过它不是作用于整个任务上的,而是作用于单个Activity上。如果某个Activity将这个属性设置成true,那么用户一旦离开了当前任务,再次返回时这个Activity就会被清除掉。