Activity基础使用
Activity 是一个Android项目页面的基础
我们自行创建的Activity本身是继承自Activity类,然而后期Android更新了AppCompatActivity,FragmentActivity等Activity的子类,这些我们有机会再说,Activity有一些方法是用来标记生命周期的
Activity的生命周期

之前看见过很多生命周期图,但是我还是觉得看这张更舒服,更直白一点。
其中这里面包括几个回调方法,分别代表Activity的生命周期:
- onCreate():在这个Activity首次被创建时会调用这个方法,里面一般用来初始化一些UI元素,数据或者某些需要在页面渲染之前就初始化的东西。onCreacte方法里面有个Bundle对象的参数savedInstanceState,我们可以使用它进行Activity的状态恢复。
- onStart():在Activity创建之后会首先执行这个方法,在执行完onStop之后重新唤起这个页面也会调用这个方法,通常在执行完onStart之后,下一步是使页面进入到运行状态,所以一般后面会紧跟着执行OnResume()方法使页面进入到Resumed状态,然而若是有什么异常状况也会导致页面失效,继而执行了onStop();你可以在这个方法里开始某些启动页面就要做的事情,比如启动某个动画,启动播放器,启动某个前台服务等需要在屏幕出现一些内容的操作。
- onResume():在将一个 activity 移到前台之前调用。你可以在这个方法中重新播放动画、更新 UI 元素、重启相机预览、恢复音频/视频播放或者初始化你在 onPause() 中释放的组件。
- onPause(): 在将一个 activity 移到后台之前调用。在这个方法中,应该停止和 activity 有关的展示类动作,比如动画,页面背景音效等。
- onStop(): 在onPause()调用过后,activity 进入后台之前调用。这个方法是保存数据到磁盘的好地方。如果 activity 回到前台,它后面是 onRestart() 方法,如果它即将从内存移除,则它后面是 onDestroy() 方法。
- onRestart(): 在关闭一个 activity且并未销毁,又重新打开它之前调用。它后面总是 onStart() 方法。
- onDestroy(): 这是 activity 被销毁之前你能从系统接收到的最后一个回调。在这个方法中如果你在这个页面还有资源未被释放,需要在这里释放,否则会发生内存泄漏问题。
一个Activity的生命周期大致就分这几个节点,当你写一个页面的时候你首先要考虑好在每个生命周期节点应该做那些事情,这样就不会导致你的Activity看起来很乱,也要知道一些资源的生成释放的时机,防止内存泄露或者还未生成资源就调用等问题
创建一个Activity
这个很简单,AndroidStudio已经给我做好了一键生成的功能

这个不仅仅能生成一个空的Activity,还能生成很多不同功能的Activity,比如登录模块的模板LoginActivity等
但是如果你一定要手动生成一个Activity,那就要有以下操作:
1. 新建一个类继承Activity(或者其他Activity的子类)
2. 在res/layout中新建一个layout.xml文件
3. 在Activity的onCreate方法里 setContentView(R.layout.layout);
4. 在AndroidManifest.xml中的application节点下面注册。
这样你的Activity就创建好了,然而如果你创建一个新的Activity是没有地方调用的,那就没什么意义了,通常你新建一个新的项目的时候IDE会默认给你新建一个MainActivity,这个Activity是整个程序的入口你在AndroidManifest.xml文件中会看见这个Activity的节点下面有下面这样的标签

当一个Activity带有这组标签的时候,他就被标记为APP的入口Activity,也就是APP启动的第一个Activity。
启动一个Activity
启动一个Activity方式通常有两种startActivity和startActivityForResult
这两中方式一个是单纯的启动这个Activity,一个是启动这个Activity并期待它有返回一些东西
startActivity(Intent intent)
- 这是一个简单的启动方式,这个方法是Context类的,由于我们的所有Activity都继承自Activity类,Activity又是继承自Context类的,所以我们可以直接调用这个方法,他们之间的传值用Intent
Intent intent = new Intent();
intent.setClass(当前Activity.this,目标Activity.class);
startActivity(intent);
Activity之间的通信只能使用Intent进行
startActivityForResult()
- 这是一种期待下个Activity返回动作的启动方式,这个方法是Activity类的,所以如果你只是拿到Activity的Context,是不能使用这个方法的,除非你把Context实例化成Activity。
Intent intent = new Intent();
intent.setClass(当前Activity.this,目标Activity.class);
startActivityForResult(intent,REQUEST_CODE);
这个时候你下一个页面如果结束有动作或者数据要传回到这个页面的时候你需要在目标Activity中使用setResult方法
Intent data= new Intent();
data.putExtra("tag","target")
setResult((RESULT_CODE,data));
这样你的目标activity中的“target”字符串就通过data这个Intent传回到了你之前的Activity,如果你想要获取到这个data,你需要重写Activity里的一个方法onActivityResult:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode = REQUEST_CODE && resultCode == RESULT_CODE){
String tag = data.getStringExtra("tag")
}
}
这样就拿到了目标Activity回传回来的tag,这里面requestCode就是在startActivityForResult时传过去的自己定义的一个int值,而resultCode是你setResult时传的值,这样当你匹配到这两个值就是你之前定义的那两个值时,就说明是目标返回的了。
大概的流程就是这样,启动方式一般就这两种
Activity的四大启动模式
Activity还有四大启动模式,分别是standard、singleTop、singleTask、singleInstance
启动一个应用,系统就会为之创建一个栈,来放置根Activity。默认情况下,一个Activity启动另一个Activity时,两个Activity是放置在同一个栈中的,后者被压入前者所在的栈,当用户按下后退键,或者finish()掉的时候后者就会从栈里弹出,这样一来就可以描述成Activity是像纸张一样一张一张的摞起来的你启动一个Activity,就是把他放到这个栈的栈顶,每退出一个Activity,就把他从栈里拿出来,而你拿出来的时候必须按照顺序拿,这个时候我们四大启动模式就有了用武之地。
配置Activity的启动模式是在AndroidManifest中的activity标签内添加android:launchMode属性
standard-默认模式
<activity
android:name=".SecondActivity"
android:launchMode="standard">
这个就是最标准的启动方式,系统默认也是这种,一般我们可以不写。这种方式就是正常的方式,最新的最先结束掉,每次启动一个Activity都会重写创建一个新的实例,不管这个实例存不存在,这种模式下,谁启动了该模式的Activity,该Activity就属于启动它的Activity的任务栈中。这个Activity它的onCreate(),onStart(),onResume()方法都会被调用。
singleTop-栈顶复用模式
<activity
android:name=".SecondActivity"
android:launchMode="singleTop">
这种方式如果栈顶不是目标Activity的话,与standard方式一样,但是如果目标Activity在栈顶的话,那么这个Activity不会被重写创建,同时它的onNewIntent方法会被调用,而且它本身的onCreate()与onStart()方法不会呗调用
singleTask-栈内复用模式
<activity
android:name=".SecondActivity"
android:launchMode="singleTask">
这个模式下,如果目标Activity在栈顶,则处理方式与SingleTop相同,如果目标Activity不在栈内,则处理方式与standard相同;但是如果这个Activity在栈内却不在栈顶,那么则会把它上面的Activity全部出栈并把目标Activity置顶,同时它的onNewIntent方法会被调用。
singleInstance-全局唯一模式
<activity
android:name=".SecondActivity"
android:launchMode="singleInstance">
该模式具备singleTask模式的所有特性,然而更牛逼的是,整个系统中就会只剩这一个实例,以singleInstance模式启动的Activity在整个系统中是单例的,如果在启动这样的Activiyt时,已经存在了一个实例,那么会把它所在的任务调度到前台,重用这个实例。
关闭Activity
通常我们关闭一个Activity的方法就是调用Activity的finish()方法
当我们调用finish()方法以后,后面的代码将不会执行,所以如果你是用startActivityForResult方式启动的Activity,那么你的setResult方法一定要放在finish()之前,否则无效。
配置变化
当发生屏幕旋转,键盘显示等操作时,会导致Activity重启,这样有些操作就会被中断
处理方式推荐两种:
1.重写onConfigurationChanged() 方法
2.重写onSaveInstanceState()方法
重写onConfigurationChanged() 方法
首先在AndroidManifest的activity节点内添加android:configChanges属性
<activity
android:name=".newprogressplayer.MusicPlayerActivity"
android:configChanges="orientation|screenSize"
/>
然后在该Activity类内部重写onConfigurationChanged方法
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
你可以对 newConfig对象进行检查,读取 configuration 的字段,进行适当的修改界面上所用的资源。
重写onSaveInstanceState()方法
持有一个状态对象,将它传递给 activity 的重建的实例。你可以实现 onSaveInstanceState() 回调来达到这个目的
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
}
在这种方式下,Bundle只能储存序列化的对象,而在配置变化发生时进行序列化和反序列化数据会导致较大的性能开销。它会消耗大量内存,并降低 activity 的重启速度。
总结
这里只是简单介绍了一下Activity的基础知识,编程里面水深了去了,总有一些神奇的操作能让你重新认识这个你本来认为你已经会的东西,所以,活到老学到老,我先记一笔,回头忘了或者不清晰的时候再看看。
本文介绍了Android中Activity的基础知识,包括Activity的生命周期、创建与启动方式、四大启动模式及关闭方法等内容。
280

被折叠的 条评论
为什么被折叠?



