Activity生命周期。
启动Activity: onCreate()—>onStart()—>onResume(),Activity进入运行状态。
Activity退居后台: 当前Activity转到新的Activity界面或按Home键回到主屏: onPause()—>onStop(),进入停滞状态。
Activity返回前台: onRestart()—>onStart()—>onResume(),再次回到运行状态。
Activity退居后台,且系统内存不足, 系统会杀死这个后台状态的Activity(此时这个Activity引用仍然处在任务栈中,只是这个时候引用指向的对象已经为null),若再次回到这个Activity,则会走onCreate()–>onStart()—>onResume()(将重新走一次Activity的初始化生命周期)
锁屏:
onPause()->onStop()
解锁:
onStart()->onResume()
通过Acitivty的xml标签来改变任务栈的默认行为
- singleTop : 栈顶复用模式。这种模式下,如果新Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,所以它的启动三回调就不会执行,同时Activity的
onNewIntent()
方法会被回调。如果Activity已经存在但是不在栈顶,那么作用与standard模式一样。 - singleTask: 栈内复用模式。创建这样的Activity的时候,系统会先确认它所需任务栈已经创建,否则先创建任务栈。然后放入Activity,如果栈中已经有一个Activity实例,那么这个Activity就会被调到栈顶。
onNewIntent()
,并且singleTask会清理在当前Activity上面的所有Activity(clear top) - singleInstance : 加强版的singleTask模式,这种模式的Activity只能单独位于一个任务栈内,由于栈内复用的特性,后续请求均不会创建新的Activity,除非这个独特的任务栈被系统销毁了。
Activity的堆栈管理以ActivityRecord为单位,所有的ActivityRecord都放在一个List里面。可以认为一个ActivityRecord就是一个Activity栈
Activity缓存方法
onSaveInstanceState()
回调方法,一定会在Activity被回收之前调用。方法中有一个Bundle参数,putString()、putInt()等方法需要传入两个参数,一个键一个值。数据保存之后会在onCreate中恢复,onCreate也有一个Bundle类型的参数。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//这里,当Acivity第一次被创建的时候为空
//所以我们需要判断一下
if( savedInstanceState != null ){
savedInstanceState.getString("anAnt");
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("anAnt","Android");
}
-
onSavaInstanceState() 方法被调用的几种情况
1.当按下HOME键时:
因为系统不知道你按下HOME键后要运行多少其他的程序,自然也不知道Activity是否会被销毁,故系统会调用onSaveInstanceState()
,让用户有机会保存某些非永久性的数据。
2.按下多任务键,选择运行其他程序时。
3.按下电源键锁屏时。
4.从当前Activity中启动一个新的Activity时。
5.屏幕方向切换时:
在屏幕切换之前系统会销毁当前Activity,在屏幕切换之后系统又会自动地创建该Activity,所以该方法一定会被调用。
总而言之,onSaveInstanceState()
的调用遵循的原则是:当系统“未经许可”销毁了你的Activity时,就会被调用。因为系统必须提供一个让你保存数据的机会。
- 注意:
1.布局中的每一个View默认实现了onSaveInstanceState()
方法,这样的话,这个UI的任何改变都会自动地存储和在activity重新创建的时候自动地恢复。但是这种情况只有在你为这个UI提供了唯一的ID之后才起作用,如果没有提供ID,app将不会存储它的状态。
2.由于onSaveInstanceState()
方法调用的不确定性,你应该只使用这个方法去记录activity的瞬间状态(UI的状态)。不应该用这个方法去存储持久化数据。当用户离开这个activity的时候应该在onPause()
方法中存储持久化数据(例如应该被存储到数据库中的数据)。
3.onSaveInstanceState()
如果被调用,这个方法会在onStop()
前被触发,但系统并不保证是否在onPause()
之前或者之后触发。
Fragment的生命周期以及与Activity之间的关系
注意和Activity相比的区别:
onAttach() onDetach()
onCreateView() onDestoryView()
Intent的使用方法,可以传递哪些数据类型?
通过查询Intent/Bundle的API文档,我们可以知道,Intent/Bundle支持传递基本类型的数据和基本类型的数组数据,以及String/CharSequence类型的数据和String/CharSequence类型的数组数据。而对于其他类型的数据或数组数据则可以使对象序列化,例如实现Parcelable接口或实现Serializable接口。
为什么在Service中创建子线程而不是在Activity中?
这是因为Activity很难对Thread进行控制,当Activity被销毁之后,就没有任何其它的办法可以再重新获取到之前创建的子线程的实例。而且在一个Activity中创建的子线程,另一个Activity无法对其进行操作。但是Service就不同了,所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例。因此,使用Service来处理后台任务,Activity就可以放心地finish,完全不需要担心无法对后台任务进行控制的情况。
Service的两种启动方法是?有什么区别?
1.在Context中通过public boolean bindService(Intent service, ServiceConnectionconn, int flags)
方法来进行Service与Context的关联并启动,并且Service的生命周期依附于Context(不求同年同月同日生,但求同年同月同日死)。
2.通过public ComponentName startService(Intent service)
方法去启动一个Service,此时Service的生命周期与启动它的Context无关。
3.要注意的是无论如何,都需要在AndroidManifest.xml里注册你的Service
<service
android:name=".packnameName.youServiceName"
android:enabled="true" />
广播(Broadcast Receiver)的两种动态注册和静态注册有什么区别?
- 静态注册:在AndroidManifest.xml文件中进行注册,当App退出后,Receiver仍然可以接收到广播并且进行相应的处理。
- 动态注册:在代码中动态注册,当App退出后,也就没办法在接受广播了。
保证Service不被杀死的几种方法
1.Service设置成START_STICKY
- kill后会被重启(等待5秒左右),重传Intent,保持与重启前一样。
2.提升Service的优先级
在AndroidManifest.xml文件中对于intent-file可以通过android:proiority = "1000"
这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低,同样适用于广播。- 【结论】目前看来,priority这个属性貌似只适用于Broadcast,对于Service来说无效。
3.onDestroy方法里重启Service
- Service + Broadcast 方式,就是当Service执行onDestory()的时候,发送一个自定义的广播,当收到广播的时候,重新启动service。
- 也可以直接在onDestroy()里startService
- 【结论】当使用助手类软件或者直接在设置里强制停止应用时,App进程直接被结束,onDestroy方法都进不来,还是无法彻底保证。
4.监听系统广播判断Service状态
- 通过系统的一些广播,比如:手机重启、界面唤醒、应用状态改变等等监听并捕获到,然后判断我们的Service是否还存活。
- 【结论】这也能算是一种措施,不过见听多了会导致Service很混乱,不方便。
5.root之后放到System/app变成系统级应用
6.放一个像素在前台
如何判断应用被强杀
在Application中定义一个Static常量,赋值为-1,在Splash界面改为0,如果被强杀,application重新初始化,在父类Activity判断该常量的值。
应用被强杀如何解决
如果在每一个Activity的onCreate里判断是否被强杀,冗余了,封装到Activity的父类中,如果被强杀,跳转回主界面,如果没有被强杀,执行Activity的初始化操作,给主界面传递intent参数,主界面会调用onNewIntent方法,在onNewIntent跳转到欢迎页面,重新来一遍流程。
Asset目录与res目录的区别
res 目录下面有很多文件,例如 drawable,mipmap,raw 等。res 下面除了 raw 文件不会被压缩外,其余文件都会被压缩。同时 res目录下的文件可以通过R 文件访问。Asset 也是用来存储资源,但是 asset 文件内容只能通过路径或者 AssetManager 读取。
Android怎么加速启动Activity
启动应用 :Application 的构造方法,onCreate 方法中不要进行耗时操作,数据预读取(例如 init 数据) 放在异步中操作
启动普通的Activity:A 启动B 时不要在 A 的 onPause 中执行耗时操作。因为 B 的 onResume 方法必须等待 A 的 onPause 执行完成后才能运行
Android内存优化方法:ListView优化,及时关闭资源,图片缓存等等。
View和View Group的区别?自定义View的过程?
Android的UI界面都是由View和ViewGroup及其派生类组合而成的。其中,View是所有UI组件的基类,而 ViewGroup是容纳这些组件的容器,其本身也是从View派生出来的。View对象是Android平台中用户界面体现的基础单位。View类是它称为“widgets(工具)”的子类的基础,它们提供了诸如文本输入框和按钮之类的UI对象的完整实现。ViewGroup类同样为其被称为“Layouts(布局)”的子类奠定了基础,它们提供了象流式布局、表格布局以及相对布局之类的布局架构。
-
如何自定义控件:
1.自定义属性的声明和获取- 分析需要的自定义属性
- 在res/values/attrs.xml定义声明
- 在layout文件中进行使用
- 在View的构造方法中进行获取
2.测量onMeasure
3.布局onLayout(ViewGroup)
4.绘制onDraw
5.onTouchEvent
6.onInterceptTouchEvent(ViewGroup)
7.状态的恢复与保存
Content的区别
- Activity和Service以及Application的Context是不一样的,Activity继承自ContextThemeWraper.其他的继承自ContextWrapper
- 每一个Activity和Service以及Application的Context都是一个新的ContextImpl对象
- getApplication()用来获取Application实例的,但是这个方法只有在Activity和Service中才能调用的到。那么也许在绝大多数情况下我们都是在Activity或者Service中使用Application的,但是如果在一些其它的场景,比如BroadcastReceiver中也想获得Application的实例,这时就可以借助getApplicationContext()方法,getApplicationContext()比getApplication()方法的作用域会更广一些,任何一个Context的实例,只要调用getApplicationContext()方法都可以拿到我们的Application对象。
- Activity在创建的时候会new一个ContextImpl对象并在attach方法中关联它,Application和Service也差不多。ContextWrapper的方法内部都是转调ContextImpl的方法
- 创建对话框传入Application的Context是不可以的
- 尽管Application、Activity、Service都有自己的ContextImpl,并且每个ContextImpl都有自己的mResources成员,但是由于它们的mResources成员都来自于唯一的ResourcesManager实例,所以它们看似不同的mResources其实都指向的是同一块内存
- Context的数量等于Activity的个数 + Service的个数 + 1,这个1为Application
IntentService的使用场景与特点
IntentService是Service的子类,是一个异步的,会自动停止的服务,很好解决了传统的Service中处理完耗时操作忘记停止并销毁Service的问题
优点:
- 一方面不需要自己去new Thread
- 另一方面不需要考虑在什么时候关闭该Service
onStartCommand中回调了onStart,onStart中通过mServiceHandler发送消息到该handler的handleMessage中去。最后handleMessage中回调onHandleIntent(intent)。