Activity、Service、Task、Process和Thread的关系

Activity, Service,Task, Process and Thread之间到底是什么关系呢?
我们可以把TASK看成一个应用程式本身,当使用者点击应用程式以后,就启动了TASK,而TASK就可以看成一个或多个activity。当应用程式启动,程式会依我们最先开启的Activity,在堆叠里,开出一个Task(任务)空间,然后呢,它被放在Task的最顶层
每一个程序默认都运行于其独立的Linux进程中。当任何一段代码需要被执行时Android会开始一个进程,而当它不再被需要或当其它程序请求系统资源时进程将被关闭。
每一个进程有其自己的虚拟机,因此程序代码的运行和所有其他程序是孤立开的。
每一个程序默认被分配一个专属的Linux用户ID。由于设立的权限,因此程序的文件仅对该用户和程序可见。同时也有很多方法将程序文件输出给外部程序。
同一个应用程序的Activity一般都是在同一个进程中启动,事实上,Activity也可以像Service一样在新的进程中启动(注意,service是在新进程中启动的而不是新线程),这样,一个应用程序就可以跨越好几个进程了,本文就分析一下在新的进程中启动Activity的方法和过程。
第一次开启应用程式,Android将启动一个只有一个执行线程的进程,而这个线程就是mainthread,因为主要用来处理与使用者的沟通,也因此叫做UIthread——主Activity运行时,如果你没有在里面产生其它thread,那就在这个Activity的默认thread运行,实际上刚启动的Activity也是开了一个thread,只不过这个thread是Activity的UI thread,与界面直接相关,几乎是仅仅用来更新界面用的,而如果之后你又在这个Activity里开其它thread,那这些thread虽然也是属于这个Activity的,但就不是UI thread了,换句话说,一个Activity只有一个UI thread,这个UI thread专门负责管更新界面的。一个进程可能有若干个Activity。Activity退出后,进程可能并没有结束。下次用户从桌面启动该Activity时,会直接使用没有结束的进程。所以,想直接在主Activity中做程序初始化之类的操作,则需要小心。(实际上,Activity没有主次之分,说它是“主”,主要是因为它接受ndroid.intent.action.MAIN action) 
首先我们来看下Task的定义,Google是这样定义Task的:a task is what the user experiences as an "application." It's a group of related activities, arranged in a stack. A task is a stack of activities, not a class or an element in the manifest file. 这意思就是说Task实际上是一个Activity栈,通常用户感受的一个Application就是一个Task。从这个定义来看,Task跟 Service或者其他Components是没有任何联系的,它只是针对Activity而言的。
而Service和Activity只是Android提供的Components中的两种,除此之外还有Content Provider和Broadcast Receiver。
通常情况下,对于一个应用程序的所有的Components都会在同一个Process产生的Main Thread中运行。但是我们也可以让不同的Component运行在不同的Process当中,我们可以通过设置这些Components的属性来使其运行在不同的Process当中,例如:<activity android: process = "processA">。当然我们也可以设置使他们运行在同一个Process当中,即使他们不在同一个应用程序当中也可以(前提是这些应用程序使用的是同一个Linux User ID,并且被同一个机构签名)。
那么Thread跟这些Components又有什么关系呢?
通常我们会将一些长时间或大计算量的操作用一个单独的线程来运行,以防止类似操作阻塞Process。比如我们可以为一个Service(如播放音乐的Service)产生一个Thread,我们也可以为Methods来产生一个线程。总之当你不想让某些操作阻塞Main Thread的时候,create a thread!
 
就算是activity都退出了,进程也不一定结束。进程不结束,进程内的静态数据就不会消失。 


进程什么时候被终止?根据官方文档描述,一个重要的条件是,当系统发觉内存过少时,则会把一些没有处于前台的activity进程结束掉。我们可以使用DDMS直接终止进程。终止进程后,再启动activity,则会得到第一次的日志输出。
值得注意的是,如果我们的进程结束掉了,那么注册的ContentObserver则不会被调用。相反,如果进程依然存在,就算没有activity,ContentObserver也会被调用,并且不会创建其他activity。 
就算进程不在,BroadcastReceiver也会被调用,并且创建对应的进程。但是,并不会创建任何Activity。 
——————————————————————————————————————————————
一个很好的编程经历:
现在是这样一个问题,整个程序就一个Activity,它接受GPS信息,第一次获取到位置的时候启动一个后台线程,该线程是包含UDP服务端和客户端,start之后除非调用自定义的方法exit()否则不会退出。而这个exit方法是在Activity的onDestroy()里面调用的。但是目前发现这样的一个问题,就是,按了home键之后,程序执行了onStop()方法,然后点击程序图标此时会执行onCreate()方法,而不是理想中的onStart()方法。这样再获取到位置之后就会报错,我想应该是Activity被系统回收导致重新create了一个,但是后台线程没有退出,导致端口冲突。
而且最郁闷的是按home键的行为并不是每次都一样的,一般开机第一次肯定会是按了home,再点就是onCreate(),以后随机……
用的机器是摩托的mt710,在模拟器上没有这样的问题,在华为U8220上也有类似问题。
现在我想解决这个问题,请问有没有好的办法呢?
回复:
    activity被回收,线程应该会关闭的,添加android:launchMode="singleInstance" 试试。
    Activity被回收,那么它打开的线程会不会关闭,一般的做法是设置标志位,好像是这样
    做下同步,如果onstop了,那就让线程停止
    现在的情况是如果按了home,会执行onStop(),再点程序图标,这时候当后台线程运行的时候就会出现问题,我想是因为端口冲突,实际上也是这样,因为我把端口设成0之后就不用强制关闭了。
    能否详细说说怎么设置标志位?
    onStop()的时候线程不能停止,因为要侦听服务器发送来的信息,还要响应心跳报文。
    那你可以在onCreate()判断,如果线程是start状态的,就先stop掉,再重新start
    Activity中开的线程是不会因为Activity的关闭而关闭的。如果你的线程是while(true)循环工作,那么,将true值改成变量控制,要关闭线程,就让变量的值为false,则线程允许即可结束。Java里面线程的结束不能使用stop()方法的,连destroy(),interupt()方法都经常不起作用,并且,这两个方法总会引来多线程问题。所以,对于while(true)执行的线程,通常用改变while条件,来让线程结束运行是最好的方式,不会出错。如果线程不是while(true)执行,那么,线程执行玩所有操作会自动结束的,不用你操心。
   你在onResume里面启动,OnPause里面退出,就没有问题了。如果要一直运行,就做成一个RPC的service吧
  不会停止。所以应该处理状态同步。建议不要用子线程来做,用 service 。然后用 bindService 的方式来启动服务。在 Activity 退出时,Service 也将被回收。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值