Android系统service组件的线程关系
Service是Android系统提供的4大组件之一,我们在应用的开发过程中会经常通过AIDL的方式用到。但是当应用在使用该service服务时,服务提供的方法所运行在的线程却不是很清楚,本文通过一些代码实验给出初步的结论,不足处请更正:
初步结论:
1. 当服务是本地服务时(即服务和服务的使用者是一个进程),service服务组件提供的方法所运行在的线程 取决于 调用此方法的调用者所处的线程。 我们在教科书上获 得信息是:本地服务是运行在主线程中的,如果提供的方法太耗时,会产生ANR。此情况的前提是,访问此方法的调用者就是主线程,即一般TID为1的线程;如果我们在子线程中访问服务提供的方案,那么本地服务中的方法所运行在的线程就是调用此方法的线程。所以对于本地服务,服务提供的方法所运行在的线程,取决于调用者所在的线程。
2. 当服务不是本地服务时(即服务和服务的使用者不是一个进程,有设置process属性),service服务组件提供的方法所运行在的线程 与 调用者无关,因为是跨进 程访问。那么在service服务所在进程中,service提供的方法被访问时,方法所运行在的线程不是service的主线程,而是子线程。此子线程是在service组件 被 新创建的进程加载前,系统为该进程创建的binder线程。
代码比较简单,在如下 MainActivity 中调用服务提供的方法:
public class MainActivity extends Activity {
public final String TAG = "MainActivity" ;
private Iservicetest serviceTest = null;
private static final HandlerThread sWorkerThread = new HandlerThread( "service-worker");
static {
sWorkerThread.start();
}
private static final Handler sWorker = new Handler(sWorkerThread.getLooper());
private static final Handler mWorker = new Handler(
Looper.getMainLooper());
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
boolean retVal = false ;
setContentView(R.layout.activity_main);
Intent bindItent = new Intent(MainActivity.this,servicetest.class);
retVal = bindService(bindItent,serviceTestConnection,Context.BIND_AUTO_CREATE);
Log.d(TAG,"bindService="+retVal);
Log.d(TAG,"ThreadID="+Thread.currentThread().getId());
sWorker.postDelayed(new Runnable(){
@Override
public void run() {
try{
Log.d(TAG," sWorker ThreadID="+Thread.currentThread().getId());
serviceTest.getVal(0);
serviceTest.setVal(0);
} catch (Exception e) {
e.printStackTrace();
return;
}
}
},2000);
mWorker.postDelayed(new Runnable(){
@Override
public void run() {
try {
Log.d(TAG," mWorker ThreadID="+Thread.currentThread().getId());
serviceTest.getVal(0);
serviceTest.setVal(0);
} catch (Exception e) {
e.printStackTrace();
return;
}
}
},2000);
}
如下是示意的service服务的代码:
private ServiceConnection serviceTestConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className ,IBinder service){
Log.d(TAG,"servie onServiceConnected");
serviceTest = Iservicetest.Stub.asInterface(service);
Log.d(TAG," onServiceConnected ThreadID="+Thread.currentThread().getId());
}
public void onServiceDisconnected(ComponentName className){
serviceTest = null;
Log.d(TAG,"servie disconnected");
Log.d(TAG," onServiceDisconnected ThreadID="+Thread.currentThread().getId());
}
};
public class servicetest extends Service {
public String TAG = "servicetest" ;
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG," servicetest onCreate threadID="+Thread.currentThread().getId());
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.d(TAG," servicetest onBind threadID="+Thread.currentThread().getId());
return stub;
}
private Iservicetest.Stub stub = new Iservicetest.Stub() {
public int getVal(int addr ){
Log.d(TAG," getVal TID="+Thread.currentThread().getId());
return 0;
}
public int setVal(int val ){
Log.d(TAG,"setVal TID="+Thread.currentThread().getId());
return 0;
}
};
}