概览
2.四大组件之一:Activity的基本用法
2.1 概述
一个Android应用中,可以有多个Activity。组成Activity栈,当前活动的Activity位于栈顶,之前的Activity被压入下面,成为非活动的Activity,等待是否可能被恢复为活动状态。
2.2 创建、配置、启动和关闭活动
2.2.1 创建Activity
-
通过AS编译器创建: 右键包名->NEW->Activity->Empty Activity
-
手动创建: 右键包名->NEW->Activity->Empty Activity
- 不要勾选Launcher Activity(自动将活动设置为主活动) 和Generate LayoutFile(自动创建对应的布局文件)
- 手动创建布局文件:res目录右键->New Directory->创建layout目录右键-> NEW Layout resource file
- 设置要显示的布局管理文件
2.2.2 配置Activity
如果没有AndroidManifest.xml文件中配置,而又在程序中启动Activity,那么将抛出异常
具体配置:在 application标签中添加activity,每个Activity对应一个标签
配置Activity时通常需要指定的属性:
- android:name:指定对应的Activity实现类
如果在package属性指定的包中,可以直接写类名或.类名,如果在package属性指定包的子包中,则属性需要设为完整包路径 - android:label:为该Activity指定标签即标题栏的内容
- android:theme:设置要应用的主题
2.2.3 启动Activity
- 在一个应用中,如果只有一个Activity,那么只需要在AndroidManifest.xml文件中,将其设置为程序的入口,运行该项目时,将自动启动该Activity。
<!-- 在<activity>标签中配置intent-filter -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
- 在一个应用中,存在多个Activity,需要应用startActivy()方法来启动需要的Activity。
- 使用显示Intent跳转
Intent intent = new Intent(启动活动的上下文.this,要跳转到的活动.class);
startActivity(intent);
- 使用隐式Intent跳转
在Manifest文件中,在需要跳转的activity标签中配置响应的action和category,如果有需要还可以配置需要响应的data标签。然后给intent添加action和category。只有data标签中指定的内容和Intent携带的data完全一致,当前活动才可以响应Intent
配置 intent-filter:
<!-- 使用隐式intent 需要配置 intent-filter -->
<intent-filter>
<!-- 只有<action> 和 <category>中的内容同时能够匹配上Intent中指定的action个category,这个活动才能响应Intent -->
<action android:name="指定的action" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="指定的category" />
<data
android:scheme="" 协议
android:host="" 主机
android:port="" 端口
android:path="" 主机名和端口之后的部分
android:mimeType="" 可以处理的数据类型,允许使用通配符
>
</data>
</intent-filter>
给intent添加action和category:
//必须指定一个action
Intent intent = new Intent("指定action字符串");
intent.addCategory("指定category");
//指定当前正在操作的数据
intent.setData(Uri对象);
//category默认为DEFAULT,该方法会自动将category添加到Intent中
startActivity(intent);
2.2.4 关闭Activity
销毁活动:在单击按钮时关闭,直接调用 finish()方法。如果当前Activity不是主活动,那么执行finish()方法后,将返回到调用它的Activity,否则将返回到主屏幕。
2.3 传递数据以及返回数据
2.3.1 向下一个活动传递数据
使用 putExtra() 方法传递数据, 方式:键-值,然后在目标activity中将数据取出。
示例:
//在当前活动中
//使用putExtra()方法传递数据 键-值
intent.putExtra("键",value);
//在目标活动中取出:
Intent intent = getIntent(); //获取启动 该Activity的intent
String data = intent.getStringExtra("键");//根据键获取值
2.3.2 返回数据给上一个活动
-
需要使用 startActivityForResult(intent,1);方法启动 1为请求码(设定为唯一值),用于在回调方法中判断数据来源
-
在目标activity中 构建Intent并传入数据,使用 setResult(RESULT_OK,intent)方法,用于向上一个活动返回处理结果一般只使用(RESULT_OK/RESULT_CANCELED)
-
在上一个活动中重写onActivityResult()方法接收销毁的Activity返回的数据
- 先判断请求码 requestCode是否为传入的请求码判断数据来源
- 再判断resultCode处理结果是否为RESULT_OK 最后从data中将数据取出来
示例:
//使用startActivityForResult()方法启动活动
startActivityForResult(intent,1);
//在目标Activity中
Intent resIntent = new Intent();
resIntent.putExtra();
//处理结果 RESULT_ok RESULT_CANCELED 带有数据的intent传递回去
setResult(RESULT_OK, resIntent);
finish(); //直接销毁活动
//在上一个活动重写onActivityResult()方法接收销毁的Activity返回的数据
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case 1:
if (resultCode == RESULT_OK) {
//获取数据
String returnData = data.getStringExtra("键");
}
break;
default:
break;
}
}
2.4 活动的生命周期
2.4.1 活动状态
4个活动状态:
- 运行状态:当前的Activity,位于Activity栈顶,用户可见,并且可以获得焦点
- 暂停状态:失去焦点的Activity,任然可见,但是在内存低的情况下,不能被系统killed
- 停止状态:该Activity被其他Activity所覆盖,不可见,但是它仍然保存所有的状态和信息,当内存低的情况下会被系统killed
- 销毁状态:该Activity结束,或Activity所在的虚拟器进程结束。
2.4.2 活动的生存期
3种生存期:
- 完整生存期:onCreate()到onDestroy() 之间所经历的
- 可见生存期:onStart()到onStop() 之间所经历的
- 前台生存期:onResume()到onPause()方法之间所经历的
完整生命周期:
- onCreate():在第一次创建时被调用
- onStart():由不可见变为可见时调用
- onResume(): 准备好交互时调用,此时活动位于栈顶,且处于运行态
- onPause():准备启动或恢复另一个活动时调用,通常释放资源,保存关键数据
- onStop(): 完全不可见时调用
- onRestart(): 由停止状态变为运行状态之前调用,被重新启动
- onDestroy():在活动被销毁之前调用,变为销毁状态
2.4.3 保存被回收的活动的数据
- 在activity中重写onSaveInstanceState()方法,进行数据的保存
- 在onCreate()方法中进行恢复
示例:
//重写
//将临时数据进行保存
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
String tempData = "要保存的数据";
outState.putString("data_key",tempData);
}
//在onCreate()方法中取出数据
if (savedInstanceState != null){
String tempData = savedInstanceState.getString("data_key");
}
也可以把传递的数据保存再Bundle中,再将Bundle存在Intent中,到目标活动中从Intent中取出Bundle,在从Bundle中取出数据
示例:
Intent intent = new Intent(MainActivity.this,目标Activity.class);
Bundle bundle = new Bundle();
String transData = "transform data";
bundle.putString("send_data",transData);
intent.putExtra("bundle",bundle);
startActivity(intent);
//在目标activity中取出bundle
Intent intent = getIntent();
Bundle bundle = intent.getBundleExtra("bundle");
String acceptData = bundle.getString("send_data");
2.5 活动的启动模式
其中singleTop、singleTask、singleInstance 要在Manifest文件中activity标签中通过android:launchMode指定
- standard:系统默认的启动模式 每次启动时都会创建一个activity
- singleTop activity:在栈顶时再次启动activity会直接使用,不会创建新的活动,当活动并未在栈顶,仍会创建新的实例
- singleTask:每次启动活动都会在返回栈中检查是否存在该实例,如果有则直接使用并且把该活动之上的全部活动出栈,如果没有则直接创建
- singleInstance:会启用一个新的返回栈来管理活动都是共用的同一个返回栈
2.6 活动的最佳实践
2.6.1 知晓当前是在哪一个活动
在同一个包下创建BaseActivity普通Java文件,让其继承自AppCompatActivity,然后重写onCreate()方法,
通过Log将类名打印,然后让其他的Activity都继承自BaseActivity,每当进入一个新的活动界面,该活动类名就会打印出来
2.6.2 随时退出程序
创建一个专门的集合类对活动进行管理
示例:
public class ActivityCollector {
public static List<Activity> activities = new ArrayList<>();
public static void addActivity(Activity activity){
activities.add(activity);
}
public static void removeActivity(Activity activity){
activities.remove(activity);
}
public static void finishAll(){
for (Activity activity:activities){
if(!activity.isFinishing()){
activity.finish();
}
}
activities.clear();
}
}
在BaseActivity onCreate()中调用addActivity方法,再重写onDestroy()方法中调用removeActivity方法
如果是想立即退出程序,调用finishAll()方法,
示例:
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("BaseActivity",getClass().getSimpleName());
//启动活动时添加
ActivityCollector.addActivity(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
//销毁活动时移除
ActivityCollector.removeActivity(this);
}
}
//杀掉当前程序的进程,不能杀掉其他程序
android.os.Process.killProcess(android.os.Process.myPid());
2.6.3 启动活动的最佳写法
在需要启动的activity中编写静态方法,上下文对象和需要的数据类型
示例:
public static void actionStart(Context context,String data1,String data2){
Intent intent = new Intent(context,SecondActivity.class);
intent.putExtra("param1",data1);
intent.putExtra("param2",data2);
context.startActivity(intent);
}
在当前活动调用 actionStart()方法,传入上下文对象,和数据(根据数据类型传参)