“黑发不知勤学早,白首方悔读书迟。”让我们用知识武装大脑,让知识的力量推动我们一路向西.......
Android四大组件之一activity也是四大组件中最重要的一个。上一章节我已经将四大组件是什么初步做了一个介绍,接下来我就activity的知识做一个总结。
生命周期(如下图):
- activity的生命周期涉及到的函数:
- protected void onCreate(Bundle savedInstanceState):Activity被创建时调用
- protected void onStart():Activity被创建或者从后台回到前台时调用
- protected void onRestart():Activity从后台回到前台时调用
- protected void onResume():Activity创建或者或者从被覆盖、后台重新回到前台时调用
- protected void onPause():Activity被覆盖或者锁屏时被调用
- protected void onStop():Activity跳转到新的Activity或者退出时调用
- protected void onDestroy():Activity退出时调用
- activity的三大关键循环:
- 整个的生命周期,从onCreate(Bundle)开始到onDestroy()结束。
- Activity在onCreate()设置所有的“全局”状态,在onDestory()释放所有的资源。例如:某个Activity有一个在后台运行的线程,用于从网络下载数据,则该Activity可以在onCreate()中创建线程,在onDestory()中停止线程。
- 可见的生命周期,从onStart()开始到onStop()结束。
- 在这段时间,可以看到Activity在屏幕上,尽管有可能不在前台,不能和用户交互。在这两个接口之间,需要保持显示给用户的UI数据和资源等,例如:可以在onStart()中注册一个IntentReceiver来监听数据变化导致UI的变动,当不再需要显示时候,可以在onStop()中注销它。onStart(),onStop()都可以被多次调用,因为Activity随时可以在可见和隐藏之间转换。
- 前台的生命周期,从onResume()开始到onPause()结束。
- 在这段时间里,该Activity处于所有 Activity的最前面,和用户进行交互。Activity可以经常性地在resumed和paused状态之间切换,例如:当设备准备休眠时,当一个 Activity处理结果被分发时,当一个新的Intent被分发时。所以在这些接口方法中的代码应该属于非常轻量级的。
- 常见的生命周期过程:
- 启动Activity:系统会先调用onCreate方法,然后调用onStart方法,最后调用onResume,Activity进入运行状态。当前Activity被其他Activity覆盖其上或被锁屏:系统会调用onPause方法,暂停当前Activity的执行。
- 当前Activity由被覆盖状态回到前台或解锁屏:系统会调用onResume方法,再次进入运行状态。
- 当前Activity转到新的Activity界面或按Home键回到主屏,自身退居后台:系统会先调用onPause方法,然后调用onStop方法,进入停滞状态。
- 用户后退回到此Activity:系统会先调用onRestart方法,然后调用onStart方法,最后调用onResume方法,再次进入运行状态。
- 当前Activity处于被覆盖状态或者后台不可见状态,即第2步和第4步,系统内存不足,杀死当前Activity,而后用户退回当前Activity:再次调用onCreate()、onStart()、onResume(),进入运行状态。
- 用户退出当前Activity:系统先调用onPause(),然后调用onStop(),最后调用onDestory(),结束当前Activity。
- Activity用来保存和恢复状态的方法如下:
- protected void onSaveInstanceState(Bundle outState)
- Activity被系统杀死时调用,如屏幕横竖屏切换Activity被销毁再重建等。
- 在Activity被覆盖或退居后台之后,系统资源不足将其杀死,此方法会被调用;
- 在用户改变屏幕方向时,此方法会被调用;
- 在当前Activity跳转到其他Activity或者按Home键回到主屏,自身退居后台时,此方法会被调用;
- Activity被系统杀死时调用,如屏幕横竖屏切换Activity被销毁再重建等。
- protected void onRestoreInstanceState(Bundle savedInstanceState)
- Activity被系统杀死后重新创建时调用,如屏幕横竖屏切换Activity被销毁再重建等。
- 在Activity被覆盖或退居后台之后,系统资源不足将其杀死,然后用户又回到了此Activity,此方法会被调用;
- 在用户改变屏幕方向时,重建的过程中,此方法会被调用。
- 我们可以重写此方法,以便可以恢复一些临时数据。onRestoreInstanceState的调用顺序是在onStart之后。
- Activity被系统杀死后重新创建时调用,如屏幕横竖屏切换Activity被销毁再重建等。
- public void onWindowFocusChanged(boolean hasFocus)
- Activity窗口获得或失去焦点时被调用,例如创建时首次呈现在用户面前;当前Activity被其他Activity覆盖;当前Activity转到其他Activity或按Home键回到主屏,自身退居后台;用户退出当前Activity。
- 透明主题从一个activity A跳转到另外一个activity B:
A:onPause()
注意不会调用onStop()方法,因此activity B finish()之后activity A不会调用onRestart()方法。
从activity B返回activity A
A:onResume()
设置activity主题透明:代码:
设置全屏:<style name="AppBaseTheme" parent="@android:style/Theme.Holo.Light"/> <!-- Base application theme. --> <style name="AppTheme" parent="AppBaseTheme"> <item name="android:windowIsTranslucent">true</item> </style> <style name="ThemeActivity" parent="@android:style/Theme.Light.NoTitleBar"> <item name="android:windowIsTranslucent">true</item> </style> <style name="WXTheme" parent="AppBaseTheme"> <item name="android:windowIsTranslucent">true</item> <item name="android:windowNoTitle">true</item> <item name="android:windowBackground">@android:color/transparent</item> </style>
- 方式1:AndroidManifest.xml
<activity android:name="MainActivity" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" />- 注意:
- 方式2:代码实现
requestWindowFeature(Window.FEATURE_NO_TITLE); // 隐藏标题栏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN); // 隐藏状态栏
注意:设置全屏的代码必须在setContentView(R.layout.main) 之前,不然会报错。
注意:设置全屏的代码必须在setContentView(R.layout.main) 之前,不然会报错@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); // 隐藏标题栏 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); // 隐藏状态栏 setContentView(R.layout.activity_main); }
- Activity横竖屏设置
- 方式1:AndroidManifest.xml
<activity android:name="MainActivity" android:screenOrientation="landscape" /> // 或者 “portrait” - 方式2:代码实现
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
- 方式1:AndroidManifest.xml
- 获取横屏方向
int orientation = this.getResources().getConfiguration().orientation;
orientation 的常用取值可以为 ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE(横屏) 或 ActivityInfo.SCREEN_ORIENTATION_PORTRAIT(竖屏)
Activity屏幕一直显示
1、AndroidManifest.xml添加权限
<uses-permission android:name="android.permission.WAKE_LOCK" />
2、代码实现
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- Activity窗口获得或失去焦点时被调用,例如创建时首次呈现在用户面前;当前Activity被其他Activity覆盖;当前Activity转到其他Activity或按Home键回到主屏,自身退居后台;用户退出当前Activity。
- protected void onSaveInstanceState(Bundle outState)
- Activity启动过程
- 使用代理模式启动到ActivityManagerService中执行。
- 创建ActivityRecord到mHistory记录中。
- 通过socket通信到Zygote相关类创建process。
- 通过ApplicaitonThread与ActivityManagerService建立通信。
- ActivityManagerService通知ActivityThread启动Activity的创建。
- ActivityThread创建Activity加入到mActivities中并开始调度Activity执行。
- Activity的属性
- taskAffinity
- 默认情况下,一个应用程序中的所有activity都有一个affinity,它们属于同一个Task。
- 每个activity可以通过<activity>中的taskAffinity属性设置单独的affinity。
- 不同应用程序中的activity可以共享同一个affinity。
- 同一个应用程序中的不同activity也可以设置成不同的affinity。
- affinity属性在2种情况下起作用:
- 启动activity的Intent对象包含FLAG_ACTIVITY_NEW_TASK标记。
- 启动activity的allowTaskReparenting被设置成true。
- 主要的Intent标记如下:
- FLAG_ACTIVITY_NEW_TASK:如果启动activity的affinity属性与当前所有的task的affinity属性都不相同,系统会新建启动activity的affinity属性的Task,并将启动activity压入新建的Task栈中,否则将启动activity压入affinity属性相同的Task中。
- FLAG_ACTIVITY_CLEAR_TOP:1. 如果已经启动了四个Activity:A,B,C和D。在D Activity里,我们要跳到B Activity,同时希望C finish掉,可以在startActivity(intent)里的intent里添加flags标记,如下所示:
这样启动B Activity,就会把D,C都finished掉,如果你的B Activity的启动模式是默认的(multiple) ,则B Activity会finished掉,再启动一个新的Activity B。Intent intent = new Intent(this, B.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent);
如果不想重新再创建一个新的B Activity,则在上面的代码里再加上:
这样B Activity就会再创建一个新的了,而是会重用之前的B Activity,同时调用B Activity的onNewIntent()方法。intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
2. 如果已经启动了四个Activity:A,B,C和D,在D Activity里,想再启动一个Actvity B,但不变成A,B,C,D,B,而是希望是A,C,D,B,则可以像下面写代码:Intent intent = new Intent(this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); startActivity(intent);
- FLAG_ACTIVITY_RESET_TASK_IF_NEEDED:如果设置该属性,并且这个activity在一个新的task中正在被启动或者被带到一个已经存在的task的顶部,这时这个activity将会被作为这个task的首个页面加载。这将会导致拥有这个应用的affinities的task处于一个合适的状态(移动activity到这个task或者activity从中移出),或者简单的重置这个task到它的初始状态
FLAG_ALLOW_TASK_REPARENTING只在resetTaskIfNeededLocked中使用了,所以只有在需要重置task的时候 该标志才有用后面我们会专门分析任务重置,一般该标记会配合其他几个标记一起使用,如LAG_FINISH_ON_TASK_LAUNCH、FLAG_ALLOW_TASK_REPARENTING、FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET。 - FLAG_ACTIVITY_SINGLE_TOP:如果当前栈顶的activity就是要启动的activity,则不会再启动一个新的activity
- launchMode,启动模式
- standard、singleTop、singleTask和singleInstance
- standard:默认模式,可省略。在这种启动模式下,都会默认创建一个新的实例。因此,这种模式允许多个重复Activity叠加。
- singleTop:这种模式允许有多个实例,但不允许多个重复Activity叠加。如果Activity位于栈顶,不会创建新的实例,而会调用onNewIntent()方法。
- singleTask:这种模式只有一个实例。在同一应用程序中启动时,若Activity不存在则在当前Task创建一个新的实例,若Activity存在则将Task中在其之上的其它Activity销毁,并调用此Activity的onNewIntent()方法。
- singleInstance:这种模式只有一个实例,并且该实例独立运行在一个Task中。这个Task只有该实例,不允许其它Activity存在。
- standard、singleTop、singleTask和singleInstance
- allowTaskReparenting :该属性设置为true,则启动activity可以从一个Task移动另一个相同affinity的Task中。
- clearTaskOnLaunch :如果栈底activity的这个属性被设置为true,一旦用户离开task,则task栈中的activity将被清空到只剩下栈底activity。这种情况与alwaysRetainTaskState相反。即使用户只是短暂地离开,task也会返回到初始状态,即只剩下栈底acitivty。
- alwaysRetainTaskState :如果栈底activity的这个属性被设置为true,则Task中的所有activity将被长时间保存。
- finishOnTaskLaunch:这个属性与clearTaskOnLaunch相似,但它只对单独的activity操作,而不是整个task。它可以结束任何activity,包括栈底的activity。当它设置为true时,当前的activity只在当前会话期间作为task的一部分存在,当用户退出activity再返回时,它将不存在。
- taskAffinity
- 整个的生命周期,从onCreate(Bundle)开始到onDestroy()结束。
只用相信自己才能获得成功!