START_NOT_STICKY
如果系统在onStartCommand()返回后停止服务,系统不会重新创建服务,除非有等待的意图需要处理.如果想避免运行不需要的服务,或者让应用可以轻松的启动未完成的任务,这是一个安全的选择。
START_STICKY
如果系统在onStartCommand()返回后停止服务,系统重新创建服务并且调用onStartCommand()函数,但是不要传送最后一个意图。相反,系统用一个空意图调用onStartCommand(),除非还有想启动服务的意图,这种情况下,这些意图会被传递.这很适合多媒体播放的情况(或类似服务),这种情况下服务不执行命令,但是会无限运行下去,等待处理任务。
START_REDELIVER_INTENT
如果系统在onStartCommand()返回后停止服务,系统使用用最后传递给service的意图,重新创建服务并且调用onStartCommand()方法, 任何未被处理的意图会接着循环处理。所以用服务处理像下载之类的可能需要立即重启的任务,非常合适。
-
多次调用 unbindService 来释放相同的连接会抛出异常,因此我创建了一个 boolean 变量来判断是否 unbindService 已经被调用过。
和Service通信的一种方式是:Messenger
ApiDemo's MessengerServiceActivities.java较好地展示了activity与service之间的双向通信:
mService = new Messenger(service);
...
Message msg = ...;
msg.replyTo = mMessenger;
mService.send(msg)
Note: Only activities, services, and content providers can bind to a service—you cannot bind to a service from a broadcast receiver.
onServiceDisconnected(): This is not called when the client unbinds.
当最后一个用户从服务上解绑时,系统摧毁这个服务(除非这个服务由startService()启动)。
public void onServiceConnected(ComponentName className, IBinder service) {
mBoundService = ((LocalService.LocalBinder)service).getService(); // 获取到的mBoundService可以在你的Activity里面使用
}
stopSelfResult(int startId)
finish
singleTop: 复用栈顶 OnNewIntent() 使用场景:browser's bookmark (LESS_TO_READ: 如果存在多个页面存在保存书签的JavaScript脚本,就会导致书签页面被多次开启)
singleTask: 新建一个,并将其作为task的root;若此activity存在, 则调用其OnNewIntent(), 并清空其之上的所有activity, 与singleInstance不同的是,新启动的task不排他。对应于Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT。
使用场景:程序的主页面: 当程序有进入到主页面的时候,清除BackStack中,它之上的所有Activity,这样避免程序导航逻辑的混乱。 比如Android系统的浏览器的主页面,就是singleTask模式的
加singleTask的activity最好加上action_main和category_launcher, 否则用户不好找回。
略:Note: Although the activity starts in a new task, the Back button still returns the user to the previous activity.
singleInstance 使用场景:适用于需要在系统中只存在一个实例的场景,比如Android系统的来电页面,多次来电均使用的是一个Activity。
通过代码设置的启动模式的方式,优先级要高于在AndroidManifest.xml中的配置
================================================================
Affinity:
-
以flag_new_task启动activity时,系统将新建的activity放到与其affinity最亲近的task里面,不一定放一个空的且新的task里面
-
可以使用Activity.finishAffinity()来干掉一群相同的affinity的activity
================================================================
android:alwaysRetainTaskState 使用场景:像Browser应用程序,这里有很多的状态(例如多个打开的Tab),用户不想丢失这些状态。
clear__TaskOn__Launch:
重开task,清掉原来的activities
如果Task的根Activity的这个特性设置为“true”时,当用户离开Task并返回时,stack会清除直到根Activity。换句话说,它是alwaysRetainTaskState的另一个极端。用户总是回到Task的初始化状态,即便是一个短暂的离开。
maybe 等于: FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_SINGLE_TOP
finish__OnTask__Launch:
仅当前session期间有效
这个特性和clearTaskOnLaunch相似,但它针对单个Activity,不是整个Task。它能使任何Activity消失,包括根Activity。当它设置为“true”时,这个Activity仅在当前会话期间保持为Task的部分。如果用户离开并再次返回到这个Task,它就不再显示了。
================================================================
TaskStackBuilder tsb = TaskStackBuilder.from(this);
tsb.addParentStack(this);
tsb.addNextIntent(new Intent(this, TestActivity.class));
tsb.startActivities();
affinity属性在2种情况下起作用:当启动activity的Intent对象包含FLAG_ACTIVITY_NEW_TASK标记,或当activity的allowTaskReparenting被设置成true
======================================================================
只看加粗的部分:
FLAG_ACTIVITY_BROUGHT_TO_FRONT
这个标志一般不是由程序代码设置的,如在launchMode中设置singleTask模式时系统帮你设定。
FLAG_ACTIVITY_CLEAR_TOP(略一点)
clear_top加new_task的intent_flag组合
如果设置,并且这个Activity已经在当前的Task中运行,因此,不再是重新启动一个这个Activity的实例,而是在这个Activity上方 的所有Activity都将关闭,然后这个Intent会作为一个新的Intent投递到老的Activity(现在位于顶端)中。
例如,假设一个Task中包含这些Activity:A,B,C,D。如果D调用了startActivity(),并且包含一个指向Activity B的Intent,那么,C和D都将结束,然后B接收到这个Intent,因此,目前stack的状况是:A,B。
上例中正在运行的Activity B既可以在onNewIntent()中接收到这个新的Intent,也可以把自己关闭然后重新启动来接收这个Intent。如果它的启动模式声明为 “multiple”(默认值),并且你没有在这个Intent中设置FLAG_ACTIVITY_SINGLE_TOP标志,那么它将关闭然后重新创 建;对于其它的启动模式,或者在这个Intent中设置FLAG_ACTIVITY_SINGLE_TOP标志,都将把这个Intent投递到当前这个实 例的onNewIntent()中。
这个启动模式还可以与FLAG_ACTIVITY_NEW_TASK结合起来使用:用于启动一个Task中的根Activity,它会把那个Task中任 何运行的实例带入前台,然后清除它直到根Activity。这非常有用,例如,当从Notification Manager处启动一个Activity。
FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
如果设置,这将在Task的Activity stack中设置一个还原点,当Task恢复时,需要清理Activity。也就是说,下一次Task带着 FLAG_ACTIVITY_RESET_TASK_IF_NEEDED标记进入前台时(典型的操作是用户在主画面重启它),这个Activity和它之 上的都将关闭,以至于用户不能再返回到它们,但是可以回到之前的Activity。
这在你的程序有分割点的时候很有用。例如,一个e-mail应用程序可能有一个操作是查看一个附件,需要启动图片浏览Activity来显示。这个 Activity应该作为e-mail应用程序Task的一部分,因为这是用户在这个Task中触发的操作。然而,当用户离开这个Task,然后从主画面 选择e-mail app,我们可能希望回到查看的会话中,但不是查看图片附件,因为这让人困惑。通过在启动图片浏览时设定这个标志,浏览及其它启动的Activity在下 次用户返回到mail程序时都将全部清除。
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
如果设置,新的Activity不会在最近启动的Activity的列表中保存。
FLAG_ACTIVITY_FORWARD_RESULT
如果设置,并且这个Intent用于从一个存在的Activity启动一个新的Activity,那么,这个作为答复目标的Activity将会传到这个 新的Activity中。这种方式下,新的Activity可以调用setResult(int),并且这个结果值将发送给那个作为答复目标的 Activity。
FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
这个标志一般不由应用程序代码设置,如果这个Activity是从历史记录里启动的(常按HOME键),那么,系统会帮你设定。
FLAG_ACTIVITY_MULTIPLE_TASK
不要使用这个标志,除非你自己实现了应用程序启动器。与FLAG_ACTIVITY_NEW_TASK结合起来使用,可以禁用把已存的Task送入前台的 行为。当设置时,新的Task总是会启动来处理Intent,而不管这是是否已经有一个Task可以处理相同的事情。
由于默认的系统不包含图形Task管理功能,因此,你不应该使用这个标志,除非你提供给用户一种方式可以返回到已经启动的Task。
如果FLAG_ACTIVITY_NEW_TASK标志没有设置,这个标志被忽略。
FLAG_ACTIVITY_NEW_TASK
如果设置,这个Activity会成为历史stack中一个新Task的开始。一个Task(从启动它的Activity到下一个Task中的 Activity)定义了用户可以迁移的Activity原子组。Task可以移动到前台和后台;在某个特定Task中的所有Activity总是保持相 同的次序。
这个标志一般用于呈现“启动”类型的行为:它们提供用户一系列可以单独完成的事情,与启动它们的Activity完全无关。
使用这个标志,如果正在启动的Activity的Task已经在运行的话,那么,新的Activity将不会启动;代替的,当前Task会简单的移入前台。参考FLAG_ACTIVITY_MULTIPLE_TASK标志,可以禁用这一行为。
这个标志不能用于调用方对已经启动的Activity请求结果。
FLAG_ACTIVITY_NO_ANIMATION
如果在Intent中设置,并传递给Context.startActivity()的话,这个标志将阻止系统进入下一个Activity时应用 Acitivity迁移动画。这并不意味着动画将永不运行——如果另一个Activity在启动显示之前,没有指定这个标志,那么,动画将被应用。这个标 志可以很好的用于执行一连串的操作,而动画被看作是更高一级的事件的驱动。
FLAG_ACTIVITY_NO_HISTORY
如果设置,新的Activity将不再历史stack中保留。用户一离开它,这个Activity就关闭了。这也可以通过设置noHistory特性。
FLAG_ACTIVITY_NO_USER_ACTION
如果设置,作为新启动的Activity进入前台时,这个标志将在Activity暂停之前阻止从最前方的Activity回调的onUserLeaveHint()。
典型的,一个Activity可以依赖这个回调指明显式的用户动作引起的Activity移出后台。这个回调在Activity的生命周期中标记一个合适的点,并关闭一些Notification。
如果一个Activity通过非用户驱动的事件,如来电或闹钟,启动的,这个标志也应该传递给Context.startActivity,保证暂停的Activity不认为用户已经知晓其Notification。
FLAG_ACTIVITY_PREVIOUS_IS_TOP
If set and this intent is being used to launch a new activity from an existing one, the current activity will not be counted as the top activity for deciding whether the new intent should be delivered to the top instead of starting a new one. The previous activity will be used as the top, with the assumption being that the current activity will finish itself immediately.
FLAG_ACTIVITY_REORDER_TO_FRONT
如果在Intent中设置,并传递给Context.startActivity(),这个标志将引发已经运行的Activity移动到历史stack的顶端。
例如,假设一个Task由四个Activity组成:A,B,C,D。如果D调用startActivity()来启动Activity B,那么,B会移动到历史stack的顶端,现在的次序变成A,C,D,B。如果FLAG_ACTIVITY_CLEAR_TOP标志也设置的话,那么这 个标志将被忽略。
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
If set, and this activity is either being started in a new task or bringing to the top an existing task, then it will be launched as the front door of the task. This will result in the application of any affinities needed to have that task in the proper state (either moving activities to or from it), or simply resetting that task to its initial state if needed.
FLAG_ACTIVITY_SINGLE_TOP
如果设置,当这个Activity位于历史stack的顶端运行时,不再启动一个新的。
注意:如果是从BroadcastReceiver启动一个新的Activity,或者是从Service往一个Activity跳转时,不要忘记添加Intent的Flag为FLAG_ACTIVITY_NEW_TASK。
why can't block main_thread:
系统不会为每个组件的实例分别创建线程。所有运行于一个进程的组件都在界面线程中被实例化,并且系统对每个组件的调用都在这个线程中派发
不同的应用程序可以运行在相同的进程中。要实现这个功能,首先必须使用相同的私钥签名这些应用程序,然后必须使用 manifest 文件给它们分配相同的 Linux 用户 ID,这通过用相同的值/名定义 manifest 属性 android:sharedUserId 来做到。
你也可以设置android:process以使不同应用的组件们可以运行于同一个进程—这样需要:
-
这些应用共享同一个用户ID
-
有相同的数字证书
android:process=":remote",代表在应用程序里,当需要该service时,会自动创建新的进程。而如果是android:process="remote",没有“:”分号的,则创建全局进程,不同的应用程序共享该进程。
android:process --- This allows components in different applications to share a process, reducing resource usage --- 等效于"android:multiprocess='true' "
<略看
android:multiprocess
Whether an instance of the activity can be launched into the process of the component that started it — "true" if it can be, and "false" if not. The default value is "false".
Normally, a new instance of an activity is launched into the process of the application that defined it, so all instances of the activity run in the same process. However, if this flag is set to "true", instances of the activity can run in multiple processes, allowing the system to create instances wherever they are used (provided permissions allow it), something that is almost never necessary or desirable.
略看>
manifest文件里<Application>, <Activity>,<Service>,<receiver>和<provider>都有一个process属性来指定该组件运行在哪个进程之中
进程按照重要性从高到低一共有五个级别:
前台进程、可见进程、服务进程、后台进程[ 保存在LRU (least recently used) 列表中 ]、空进程(cached_process)
当决定关闭哪些线程时,Android系统会衡量进程们与用户的紧密程度
binder方法和ContentProvider的query(), insert(), delete(), update(),都必须thread_safe