1、fragment
fragment切换
使用
commitAllowingStateLoss()
方法进行commit()
commit
和commitAllowingStateLoss
的异同点:
1、commitAllowingStateLoss
该方法的注释:
allows the commit to be executed after an activity's state is saved. This is dangerous because the commit can be lost if the activity needs to later be restored from its state, so this should only be used for cases where it is okay for the UI state to change unexpectedly on the user.
可见该方法不会在activity或者fragment的onSaveInstanceState
之后执行,使用了该方法,可能再restore之后,不会有之前的状态。
用处场景:注释中说道,可以对于用户而言不可见,用户可能不知道到底fragment的切换发生了什么。
比方说:接收到一个推送,然后发送一个切换某个界面frament的操作。如果该UI不是可见的,那么建议使用该方法。
2、fragment中使用replace
还是hide
replace会执行销毁该fragment并重新创建的操作,但是hide则不会
hide后,覆盖在上层的fragment可能仍旧会触发下层fragment的点击操作什么的。
Notification
1、notification版本的兼容
对api 15以下,18以上需要对notification做出兼容的处理。
service
1、基本介绍
The Android system will force-stop a service only when memory is low and it must recover system resources for the activity that has user focus.
一个service**只有**
在Android系统的内存不够时才会强制停止,并且会将前台可见的activity的系统资源进行恢复。
If the service is bound to an activity that has user focus, then it's less likely to be killed, and if the service is declared to run in the foreground (discussed later), then it will almost never be killed.
如果service是bind的话,那么该service会可能性较小的被杀掉;如果service被声明为foreground(前台)的,那么该service基本上不会被系统杀掉。
但是,换言之,如果是started,并且是long-running的(长时间运行的),那么,随着时间的推移,该service被系统回收的概率会随时间增长而增大。
如果你的service是start的话,那么可能需要设计成间歇性的被系统重新启动。
被杀的话,系统会根据onStartCommand返回的值,在系统资源重新可用的情况进行重新启动该服务。
2、进程和线程(关于service何时可能会被系统回收)
正常情况下,android系统会为该application启动一个新的Linux进程和一个(single)处理的线程。这样,默认的情况下就是:该application中所有的components将会运行在这个进程和线程中(我们称之为main线程),如果一个component被启动了,并且该app早已经有了一个linux进程,那么该component将会运行在该继承的默认线程上。当然,我们也能为该app中不同的component指定不同的进程,并且在同一进程指定不同的线程。
在manifest中的不同组件<activity>,<service>,<receiver>和<provider>中使用andorid:process
进行该组件的进程的指定,这样,指定了相同进程的组件将会想用同一个linux用户ID,并且使用了想用的certificate进行指定。
<application>同样支持android:process
属性,设定的话,所有的组件将会运行在相同的进程中。
进程会被系统杀,判断的标准是:
当android系统准备杀掉一个进程的时候,会对所有的进程考量他们对于用户的重要性。举例而言,会更倾向于杀掉那些activity不可见的进程。
考量进程的重要性的依据就是:
进程的生命周期
Android系统会尽量保证一个进程在系统中存在足够长的时间,但是不可避免的就是,当系统资源不够时,新建出一个进程就需要kill掉老的进程保证新的进程有足够的资源使用。
android系统会基于,********进程中运行的****components****已以及****components****的状态********,将每个进程放进系统的“importance hierarchy”中,这样,在系统资源不够时,具有最低重要性的进程会被杀死,依次类推,进行系统资源的回收。
importance hierarchy中五种进程等级
1、Foreground Process
用户正在doing的进程,符合以下任一条件的都是:
- 一个正在和用户交互的activity,该activity已经调用了
onResume
方法; - 一个已经绑定了service的activity,并且该activity正在和用户交互;
- 调用了
startForeground
的service; - 正在执行service中的
onCreate
,onStart
,onDestroy
方法的service; - 具有一个正在执行
onReceive()
方法的BroadCastReceiver
通常而言,在特定的情况下,只有少数的Foreground进程正在运行,他们只有在系统使出浑身解数之后,系统资源还不能满足正常的android进程时,才会杀掉他们,以保证用户UI响应正常。
2、Visible Process
该进程不包括任何的前台组件(foreground components),但是仍旧能够影响到用户在屏幕上可见的内容。
符合以下两种情况之一的就是就可以认为是Visible Process
。
- activity已经走了
onPause()
方法,但是该activity仍旧希望能够和该用户进行交互。比方说一个activity上面覆盖一个Dialog; - 该进程拥有一个前台(foreground)或者可见(visiable)的activity绑定在一起。
一个visiable process被看做是非常重要的(extremely important),只有在foreground process得不到正常运行的时候,才会选择杀掉visiable process。
3、Service Process
该进程运行一个使用startService()
方法的进程,并且不符合上面两种更高优先级的进程的条件。
尽管Service Process不会和用户的UI进行交互,但是他仍旧在执行一些重要的操作,比如说:播放音乐,下载任务等等。
4、Background Process
一个持有已经执行了activity的onDestroy()
方法的process。
该进行不和用户做任何的交互,系统可以随时杀掉这些进程。
这些进程会放置在LRU中,以保证用户最先看到的被第系统首先杀掉。
如果使用者能够很好的实现activity的声明周期,那么在该进程被杀死的情况下,用户重新进入activity后,系统会restore改activity之前保存的若干状态,这样,用户的体验无细致性的差异。
5、Empty Process
该进程不拥有任何active的application components。
该种进程存在的唯一目的就是为了caching,为了方便在下一次较快的启动一个component。
系统经常杀掉这些进程为了能够:平衡进程cache和underlying kernel caches的过载系统资源。
android系统倾向于将一个进程的评级向高处评价,比方说,一个拥有service和和一个active activity,那么android系统将会将该进程评价为Visible Processe而非一个service process。
进程的优先级会不断的变化,一个服务于B进程的A进程的评级不可能比B等价低,至少一样。
基于这种进程依赖性,在某些场景下非常有用:
一个需要开启了长时间任务的activity可以开启一个service进行任务的进行,而非直接开启一个线程,这样,该任务的进程等级就至少是service process
,这就是为了在广播中使用service而非一个新的线程
来执行耗时的操作。
3、线程(Thread)
android系统不会为每个组件创建一个新的线程,默认都在UIThread中执行,并且每个component都从该UIThread中分发出去。相应的,各种系统的回调(system callbacks)都在UIThread中执行。
这样,我们经常说到的不能在UIThread中做一些耗时的操作是因为
- 耗时的操作可能会阻塞UIThread,这样,在等待了5秒之后,程序就会ANR;
- UI tool kit是线程不安全的,这样,你就不能在工作线程做UI的改变(因为可能有许多不同的工作线程)
两点建议:
1、不要阻塞UI线程;
2、不要在非UI Thread中使用Android UI toolkit。
下面的几种方法可以在工作线程中操作view在UI线程中工作:
Activity.runOnUIThread()
View.post()
View.postDelayed()