一、Activity简介
- Activity是四大组件之一,用于表现功能。
- 一个Activity通常就是一个单独的屏幕(窗口)。
- Activity之间通过Intent进行通信。
- android应用中每一个Activity都必须要在AndroidManifest.xml配置文件中声明,否则系统将不识别也不执行该Activity。
二、创建一个Activity
- 自定义类继承系统Activity
- 复写Activity中Onreate方法
- 在布局文件夹中书写相应的布局文件
- 调用setContent(R.layout.activity_main)
//参数为布局文件中的相应的文件名 - 在AndroidManifest.xml注册Activity
否则报:ActivityNotFoundException
public class BActivity extends Activity {
/**
* 复写Activity中Onreate方法
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);// 调用setContentView方法
}
}
// 布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
</LinearLayout>
// Activity组件注册,一律在<application></application>根标签中进行
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<!--
此处<intent-filter></intent-filter>声明,默认首次打开MainActivity界面
可将此代码复制到MyActivity的声明中,则表明首次打开MyActivity界面
-->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--
android:name 包名全路径 + 类名
如果需要注册的Activity在pagegeName文件夹中,则不需要指定包名
-->
<activity android:name=".BActivity" >
<intent-filter>
<action android:name="com.vince.day06.b"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity android:name="com.vince.utils.CActivity" >
<intent-filter>
<action android:name="com.vince.day06.c"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
</application>
三、启动/跳转一个Activity
1. 显示跳转:指出具体跳转的Activity名称
/**
* 源Activity
*
* @param view
*/
public void startB(View view) {
// 创建Intent意图对象,指定要跳转到的界面--BActivity.class
Intent intent = new Intent(this, BActivity.class);
// 通过putExtra()方法,设置传递值
intent.putExtra("key", "启动B成功!");
// 启动
startActivity(intent);
}
// 目标Activity
Intent newIntent = getIntent();// 获取启动BActivity的intent对象
String content = newIntent.getstringExtra("key");// 获取对象中的信息
2. 隐式跳转:系统根据action和category计算出跳转哪个界面
2.1 第一种情况:A传值—–>B接收
/**
* 源Activity
*
* @param view
*/
public void startB(View view) {
// 创建Intent意图对象
Intent intent = new Intent();
// 设置action、category
intent.setAction("com.vince.day06.b");
// intent.addCategory(Intent.CATEGORY_DEFAULT); 默认添加
// 通过putExtra()方法,设置传递值
intent.putExtra("intkey", 20);
// 启动
startActivity(intent);
}
// 目标Activity
Intent newIntent = getIntent();// 获取启动BActivity的intent对象
String content = newIntent.getstringExtra("intkey");// 获取对象中的信息
2.2 第二种情况:A传值—–>B接收,B返值—–>A接收
/**
* 源Activity
*
* @param view
*/
public void startC(View view) {
// 创建Intent意图对象
Intent intent = new Intent();
// 设置action、category
intent.setAction("com.vince.day06.c");
// 通过putExtra()方法,设置传递值
intent.putExtra("intkey", 15);
// 启动(请求码可随意取,此处取10)
startActivityForResult(intent, 10);
}
/**
* 重写onActivityResult(int requestCode, int resultCode, Intent data)方法
*
* @param requestCode
* :请求码
* @param resultCode
* :是在目标Activity调用setResult时返回的结果码
* @param data
* :是在目标Activity调用setResult时传入返回的对象
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (data != null) {
Toast.makeText(this, "返回值为" + data.getStringExtra("return"), 1000).show();
}
}
// 目标Activity
Intent intent = getIntent();// 获取启动CActivity的intent对象
int a = intent.getIntExtra("intkey", -1);// 获取对象中的信息
if (a != -1) {
Toast.makeText(this, "接收MainActivity传递过来的值为" + a, 2000).show();
}
// 新建一个Intent意图对象,用于返回值
Intent newIntent = new Intent();
// 通过putExtra()方法,设置返回值
newIntent.putExtra("return", "接收成功!");
setResult(2, newIntent);// 参数中,结果码2可以随意取
// 结束CActivity
finish();
注意:如果有多个Activity注册同样的intent-filter(即action和category相同),在启动Activity时,则会弹出多个选择框,提供给用户自主选择
四、Activity生命周期
生命周期流程图如下:
1. Activity一生中有七种不同状态
(1)onCreate()
(2)onStart()
(3)onResume()
(4)onPause()
(5)onStop()
(6)onRestart()
(7)onDestroy()
package com.danny_jiang.day06_lifecycle;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity {
private int progress;
/**
* 创建一个新的Activity实例时,此方法被调用
*
* @param savedInstanceState
* 当第一次创建Activity时,此实例为null 只有当Activity发生配置改变,或者被异常杀死时
* 此参数才有具体的实现
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e("TAGA", "onCreate---" + savedInstanceState);
if (savedInstanceState != null) { // 说明之前发生过配置改变
int savedProgress = savedInstanceState.getInt("progress");
progress = savedProgress;
}
}
/**
* 当点击Button按钮时,动态的修改模拟播放进度
*
* @param view
*/
public void progress(View view) {
Toast.makeText(this, "播放到了 " + progress++, 1000).show();
}
/**
* 当Activity发生配置改变,或者被异常杀死时,此方法会被自动调用
* 一般在此方法中做数据的保存工作,重新打开Activity时,可以取出保存的数据
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// 将当前的progress值保存到outState Bundle对象中
// 当onCreate被重新调用时,可以从此Bundle中取出progress值
outState.putInt("progress", progress);
}
/**
* 当一个Activity由不可见状态改为可见状态时,此方法会被调用
*/
@Override
protected void onRestart() {
super.onRestart();
Log.e("TAGA", "onRestart");
}
/**
* 当调用到此方法后,Activity会被显示到屏幕上
* 注意:Activity并不会获取焦点
*/
@Override
protected void onStart() {
super.onStart();
Log.e("TAGA", "onStart");
}
/**
* Activity获取焦点,用户可以与之进行交互
*/
@Override
protected void onResume() {
super.onResume();
Log.e("TAGA", "onResume");
}
/**
* Activity失去焦点,但是Activity还是显示在屏幕上
*/
@Override
protected void onPause() {
super.onPause();
Log.e("TAGA", "onPause");
}
/**
* Activity从屏幕上消失
*/
@Override
protected void onStop() {
super.onStop();
Log.e("TAGA", "onStop");
}
/**
* Activity实例被销毁,Activity声明周期结束
*/
@Override
protected void onDestroy() {
super.onDestroy();
Log.e("TAGA", "onDestroy");
}
public void btnClick(View view) {
startActivity(new Intent(this, BActivity.class));
}
}
2. 典型的几种操作分析:
2.1 打开一个应用,然后点击back键退出:
onCreate()--->onStart()--->onResume()---按back键--->onPause()--->onStop()--->onDestroy()
2.2 打开一个应用,然后点击home键退出,再重新打开应用:
onCreate()--->onStart()--->onResume()---点击home键--->onPause()---onStop()---重新打开应用--->onRestart()--->onStart()---onResume()
2.3 打开一个Activity,点击该Activity上的按钮跳转到SecondActivity:
M-onCreate()--->M-onStart()--->M-onResume()---点击跳转按钮---M-onPause()-->S-onCreate()--->S-onStart()--->S-Resume()--->M-onStop()
2.4 打开一个Activity,点击该Activity上的按钮跳转到SecondActivity,然后点击back键退出SecondActivity:
M-onCreate()--->M-onStart()--->M-onResume()---点击跳转按钮--->M-onPause()-->S-onCreate()--->S-onStart()--->S-Resume()--->M-onStop()
---点击back键退出SecondActivity--->S-onPause()-->M-onRestart()--->M-onStart()--->M-onResume()--->S-onStop()--->S-onDestroy()
2.5 打开一个Activity,然后从竖屏切换为横屏
onCreate()--->onStart()--->onResume()--切换为横屏-->onPause()--->onStop()--->onDestroy()--->onCreate()--->onStart()--->onResume()
2.6 打开一个Activity,然后从竖屏切换为横屏(onSaveInstanceState,onRestoreInstanceState):
onCreate()--->onStart()--->onResume()---切换为横屏--->onSaveInstanceState()--->onPause()--->>onStop()--->onDestroy()--->onCreate()
--->onStart()--->onRestoreInstanceState()--->onResume()
2.7 打开一个Activity,点击该Activity上的按钮跳转到ThirdActivity(ThirdActivity主题为Dialog模式),然后点击back键:
M-onCreate()--->M-onStart()--->M-onResume()--点击跳转按钮-->M-onPause()--->T-onCreate()--->T--->onStart()--->T-onResume()
--点击back键-->T-onPause()--->M-onResume()--->T-onStop()--->T-onDestroy()
2.8 打开一个Activity,然后从竖屏切换为横屏(配置android:configChanges="orientation|screenSize")
onCreate()--->onStart()--->onResume()---切换横屏--->onConfigurationChanged()
备注:
A、七个生命周期组合:
启动应用程序:onCreate、onStart、onResume
失去焦点:onPause、onStop
重新获得焦点:onRestart、onStart、onResume
退出应用程序:onPause、onStop、onDestroy
B、七个生命周期按阶段划分:
完整生命周期(The entire lifetime):onCreate() --- onDestroy()
可见生命周期(The visible lifetime):onStart() --- onStop()
前沿生命周期(焦点生命周期The foreground lifetime):onResume() --- onPause()
3. 生命周期的作用
① 当用户接到一个电话或切换到另一个程序时不会崩溃
② 当用户后台运行程序时,不会销毁有价值的系统资源
③ 当用户离开再返回某应用时,不会丢失用户的进程
④ 当手机屏幕进行横竖屏切换时,不会崩溃或者丢掉用户的进程
五、Activity启动模式
1. 任务
1.1 概念
一个任务(task)就是在执行某项工作时与用户进行交互的Activity的集合。
这些Activity按照被打开的顺序依次被安排在一个堆栈中(回退栈)。
1.2 主屏页面
设备的主屏是大多数任务的启动位置,当用户触摸一个应用程序启动器图标(或者app快捷图标),应用程序的任务就会在前台显示。
如果相关应用程序的任务不存在,那么就会有一个新的任务被创建,并且应用程序打开的“主”Activity会作为任务中的根Activity。
2. 回退栈
1.1 概念
在当前的Activity启动了另一个Activity时,这个新的Activity被放到了堆栈的顶部,并且带有焦点。前一个Activity并没有消失,
而是保存在回退栈中,此时它处于停止状态。
当用户按下回退按钮时,当前的Activity会被从回退栈的顶部弹出(被销毁),而前一个Activity被恢复。
如果用户继续按回退按钮,那么回退栈中的每个Activity会被依次弹出,前一个Activity会被显示,直到用户返回主屏(或者返回到任务开始时运行
的那个Activity)。当所有的Activity从回退栈中被删除时,这个任务就不再存在了。
**注意:堆栈中的Activity不会被重新排列。因此,回退栈的操作跟后进先出的对象结构是一样的。**
3. Activity启动模式
在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作。
在Android中Activity的启动模式决定了Activity的启动运行方式。
3.1 Activity启动模式设置(AndroidManifest.xml配置文件):
<activity android:name=".BActivity"
android:launchMode="standard">
</activity>
<activity android:name=".CActivity"
android:launchMode="singleTop">
</activity>
<activity android:name=".DActivity"
android:launchMode="singleTask">
</activity>
<activity android:name=".EActivity"
android:launchMode="singleInstance">
</activity>
3.2 Activity的四种启动模式:
A.standard(系统默认):
每次激活Activity时都会创建Activity,并放入任务栈中。
每个窗体的getTaskId()保持不变,但是this.hashCode()发生改变。
B.singleTop:
如果在任务的栈顶正好存在该Activity的实例,就重用该实例,而不会创建新的Activity对象,不过它会调用
onNewIntent()方法。
如果栈顶部不存在就会创建新的实例并放入栈顶(即使栈中已经存在该Activity实例,只要不在栈顶,都会创建
实例),会回调onNewIntent()方法。
C.singleTask:
如果在栈中已有该Activity的实例,就重用该实例(调用实例的onNewIntent())。重用时,会让该实例回到
栈顶。因此,在它上面的实例将会被移除栈。
如果栈中不存在该实例,将会创建新的实例放入栈中。
singleTop每次只检测当前栈顶的Activity是否是我们需要请求创建的,而singleTask则会检测栈中全部的
Activity对象,从上向下,如果检测到是我们所请求的则会消灭此Activity对象上面的对象,直接把检测到的我们需
要的Activity置为栈顶。
D.singleInstance:
与singleTask模式的区别是存放singleInstance模式窗口对象的回退栈不能有其他任何窗口对象。因此如果
该窗口不存在,则要新建任务来存放该singleInstance模式窗口。
也就是说getTaskId()会发现任务id发生了变化。此启动模式和我们使用的浏览器工作原理类似,在多个程序中
访问浏览器时,如果当前浏览器没有打开,则打开浏览器,否则会在当前打开的浏览器中访问。
此模式会节省大量的系统资源,因为它能保证要请求的Activity对象在当前的栈中只存在一个。