今天在一本资料上看到说Acitivity,Service都是跑在主线程,一个应用只有一个进程。我感觉到疑惑,本以为Service是后台进程中,遂翻看google API,发现如下解说:
Note that services, like other application objects, run in the main thread of their hosting process. This means that, if your service is going to do any CPU intensive (such as MP3 playback) or blocking (such as networking) operations, it should spawn its own thread in which to do that work.
也就是说Service也如Acitivity一样是运行于主线程(UI线程)中,如果Service要去做耗时的工作,也就是它的主程线去做这些事。在API中介绍什么是Service时说:
What is a Service?
Most confusion about the Service class actually revolves around what it is not://Service最让人迷惑的实际上是它不是什么。
A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of. //Service不是一个单独的进程。Service并不意味着它是运行在自己的进程中(除非特殊情况),它也是运行于应用程序进程中,是其中的一部分。
A Service is not a thread. It is not a means itself to do work off of the main thread (to avoid Application Not Responding errors).//Service 不是一个线程, 它不是意味着是做工作的主线程,它是主线程的一部分。
在API关于Processes and Threads的介绍中说到,当启动一个应用组件(如Activity)时,Android系统的会启动一个单一Thread的新的Linux进程。在默认情况下,同一应用程序的所有组件运行在同一进程和线程(称为“主”线程)。如果一个应用程序组件的启动,并且这个应用程序的进程已经存在,那么它就在这个进程中开始,并使用相同的线程执行。
我开始用代码去理解这些东西,新建一个Activity,onResume中去启动一个Service,在Service中并通过Thread.currentThread().getId()查看两个所在线程,发现是一样的。
public class TestServiceThreadActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
Log.i("TestServiceThreadActivity", "name = " + Thread.currentThread().getName());
Log.i("TestServiceThreadActivity", "id = " + Thread.currentThread().getId());
startService(new Intent(this, TestService.class));
super.onResume();
}
}
public class TestService extends Service {
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
Log.i("TestService", "name = " + Thread.currentThread().getName());
Log.i("TestService", "id = " + Thread.currentThread().getId());
super.onCreate();
}
}
最终结果:
说明都是在主线程中运行。
当我在TestService.onCreate()中加入Thread.sleep(5000);发现Activity显示也会阻塞。
但是android也提供了其它方法来使Service用起来更方便,在manifest中注册service时加入android:process=“其它(如:local)”,Service就运行于其它process中了,不会再阻塞Activity运行。
关于android:process可以参看http://developer.android.com/guide/topics/manifest/application-element.html#prmsn
android:process
The name of a process where all components of the application should run. Each component can override this default by setting its own process attribute.
By default, Android creates a process for an application when the first of its components needs to run. All components then run in that process. The name of the default process matches the package name set by the <manifest> element.
By setting this attribute to a process name that's shared with another application, you can arrange for components of both applications to run in the same process — but only if the two applications also share a user ID and be signed with the same certificate.
If the name assigned to this attribute begins with a colon (':'), a new process, private to the application, is created when it's needed. If the process name begins with a lowercase character, a global process of that name is created. A global process can be shared with other applications, reducing resource usage.
对于Service和Activity中做一些比较耗时的工作(如从网络方面取数据)可以另起一个工作线程来处理,这样ANR问题可以得到一定的避免。
Service的知识肯定还有很多其它的,其待大家分享。