文章目录
- Android
-
- 四大组件
- Android 进程优先级
- Android有main方法吗
- Manifest.xml文件中主要包括哪些信息?
- View相关
- dp、dpi、px的区别
- Activity、View、Window三者之间的关系?
- Android中内存泄漏的原因
- JNI
- Android 中的内存泄漏
- Fragment
- Android 中的数据存储技术
- Android 多进程通信(ICP)
- 为什么不能在子线程访问UI
- Handle
- AsyncTask
- 线程通信
- HandlerThread
- Bitmap
- View
- ViewGroup
- margin和padding的区别
- ListView和RecycleView
- ANR
- Bundle
- Android性能优化
Android
四大组件
Activity
Activity是一个Android应用程序组件(也称为Android四大组件之一),它提供了一个屏幕,用户可以通过该屏幕进行交互以执行某些操作,例如拨打电话,拍照,发送电子邮件或查看地图。每个活动都有一个窗口,用于绘制其用户界面。窗口通常填满屏幕,但可能比屏幕小,并漂浮在其他窗口的顶部。
生命周期
Activity 应用场景
- Activity A启动:A->onCreate()->onStart()->onResume();
- 返回桌面(home键):A->onPause()->onStop();
- 桌面重新打开:A->onRestart()->onStart()->onResume();
- 退出Activity:A->onPause()->onStop()->onDestroy();
- Activity A退居后台,且系统内存不足,系统会杀死这个后台状态的Activity,若再次回到这个Activity,则会走A->onCreate()->onStart()->onResume()
- 锁屏时只会调用onPause(),而不会调用onStop方法,开屏后则调用onResume()
Activity 中启动一个新的 Activity 生命周期变化
- Activity A 启动 B
- A->onPause();
- B->onCreate()->onStart()->onResume();
- 若A此时不可见了,A->onStop()
四种启动方式
-
standard
标准模式:创建一个Activity然后放入任务栈中。 -
singleTop
栈顶复用模式:先判断栈顶Activity是否是当前需要创建的Activity,是的话就重用栈顶,否则创建再插入。 -
singleTask
任务栈单例模式:判断任务栈中是否有相同的Activity,有则移出任务栈上面的所有任务栈,使当前Activity回到栈顶,没有则重新创建。 -
singleInstance
单任务栈模式:为Activity新开一个任务栈,且只有一个实例,使该Activity独享一个任务栈,如果已经启动该实例,再次启动将会回调onNewIntent方法。
如何给Activity指定启动模式
- AndroidManifest中为Activity指定启动模式 android:launchMode=“singleTask”
- 通过在Intent中设置标记位来指定Activity的启动模式 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
Intent.FLAG_ACTIVITY_NEW_TASK,是为Activity指定“singleTask”启动模式
-
Intent.FLAG_ACTIVITY_SINGLE_TOP,是为Activity指定“singleTop”启动模式
为什么需要onNewIntent()
因为Activity启动可能会通过Intent传递参数
- 如果第一次创建,可在onCreate()内接收数据
- 如果不是第一次创建(singleTop、singleTask、singleInstance模式下),由于再次启动可能不经过onCreate(),可在onNewIntent()接收参数。
onNewIntent()方法应用场景
- Activity A从后台onStop()状态重新唤醒
- A->onStop()->onNewIntent()->onRestart()->onStart()->onResume();
- 当Activity A处于singleTop模式,此时要再次启动A:
- Activity A中启动Activity A
- A->onResume()->onPause()->onNewIntent()->onResume();
- 当Activity A处于singleTask或者singleInstance模式时:
- Activity A中启动Activity B
- Activity B中启动Activity A
- A->onStop()->onNewIntent()->onRestart()->onStart()->onResume();
onSaveInstanceState() 和 onRestoreInstanceState()
- 如果系统由于系统约束(而不是正常的应用程序行为)而破坏了Activity,那么尽管实际 Activity实例已经消失,但是系统还是会记住它已经存在,这样如果用户导航回到它,系统会创建一个新的实例的Activity使用一组保存的数据来描述Activity在被销毁时的状态。系统用于恢复以前状态的已保存数据称为“实例状态”,是存储在Bundle对象中的键值对的集合。
- 每次用户旋转屏幕时,您的Activity将被破坏并重新创建。当屏幕改变方向时,系统会破坏并重新创建前台Activity,因为屏幕配置已更改,您的Activity可能需要加载替代资源(例如布局)。即会执行onSaveInstanceState()和onRestoreInstanceState()的。
- 该方法调用在onStop之前,但和onPause没有时序关系。
- 系统onCreated()方法也可进行数据恢复,但是要判断是否Bundle为空;系统onRestoreInstanceState()只有在存在保存状态的情况下才会恢复,因此不需要检查是否Bundle为空,但是onRestoreInstanceState()在onStart()方法之后才会被调用。
注意:如果是用户自动按下返回键,或程序调用finish()退出程序,是不会触发onSaveInstanceState()和onRestoreInstanceState()的。
执行场景
- 当用户按下HOME键时
- 长按HOME键,选择运行其他的程序时
- 锁屏时
- 从activity A中启动一个新的activity时
- 屏幕方向切换时
屏幕旋转时发生什么
- Activity启动
I/System.out: onCreate
I/System.out: onStart
I/System.out: onResume
- 屏幕旋转
I/System.out: onConfigurationChanged
I/System.out: onPause
I/System.out: onSaveInstanceState
I/System.out: onStop
I/System.out: onDestroy
I/System.out: onCreate
I/System.out: onStart
I/System.out: onRestoreInstanceState
I/System.out: onResume
- 在manifest文件中加入configChanges参数
为了避免由于配置改变导致Activity重建,可在AndroidManifest.xml中对应的Activity中设置android:configChanges=“orientation|screenSize”。此时再次旋转屏幕时,该Activity不会被系统杀死和重建,只会调用onConfigurationChanged。因此,当配置程序需要响应配置改变,指定configChanges属性,重写onConfigurationChanged方法即可。
android:configChanges="orientation|screenSize"
屏幕旋转时
I/System.out: onConfigurationChanged
如何将一个 Activity 设置成窗口的样式?
android:theme="@android:style/Theme.Dialog"
如何退出APP并关闭所有Activity
- 发送特定广播
- 递归退出,就调用 finish()方法 把当前的在打开新的 Activity 时使用 startActivityForResult,然后自己加标志,在 onActivityResult 中处理,递归关闭。
Activity 怎么和 Service 通信
- 利用BroadcastReceive
- 通过Binder对象,Activity通过bindService方法开启服务,得到一个Service的对象,通过该对象可以直接和Service进行交互
Service
服务是Android中实现程序后台运行的解决方案,他非常适合是去执行那些不需要和用户交互而且还要长期运行的任务。 Service并不是运行在单独线程中,而是主线程中。所以尽量要避免一些ANR的操作。
Service的两种形式
启动本地服务用的是显式启动; 远程服务的启动要用到隐式启动
本地服务
- 该服务依附于主进程上
- 节省资源
- 当主进程被kill,服务也随之停止
远程服务
- 处于独立的线程
- 当Activity所在进程被Kill时,服务仍在运行
- 占用一定的资源,一般用于系统的Service
- 进程名格式为所在包名加上你指定的android:process字符串。一般定义方式:
android:process=":service"
Service 的两种状态
后台服务
应用组件(如 Activity)通过调用 startService() 启动服务时,服务即处于“启动”状态。一旦启动,服务即可在后台无限期运行,即使启动服务的组件已被销毁也不受影响,除非手动调用才能停止服务, 已启动的服务通常是执行单一操作,而且不会将结果返回给调用方。
如何保证Service不被杀死
后台服务在系统内存不足的时候,可能会被系统杀死,如何让服务不被杀死:
- 设置优先级(1-1000)
- 把service写成远程服务
- 把service写成前台服务
- 利用广播实时检查
- 在Service的onStartCommand()中设置flages值为START_STICKY,使得Service被杀死后尝试再次启动Service
前台服务
前台服务在手机状态栏会显示一个状态,类似于通知的效果,这样可以保证不会被系统轻易杀死。
服务的三种启动方式
startService()
生命周期是这样:调用startService()–>onCreate()–>onStartConmon()–> onDes