上次上心理學課的時候,老師講到溝通,溝通的一個必要前提是心平氣和,可是昨天我真的特別氣憤,現在的大學生怎麼變成這樣了!並不是我這個人很保守或是怎樣,不喜歡別人女生還要提出那種無恥的要求,學校裏又不是紅燈區!
好吧,算我說了一些廢話。
上回說到要Service有兩種:Started 和 Bound,已經學過了Started,因爲文檔裏專門拿出一頁來介紹Bound Service,
我估計這個Bound Service 更常用。
首先打開文檔:
http://developer.android.com/guide/topics/fundamentals/bound-services.html
1,什麼是Bound Service?
Bound Service是在C/S模式下作爲服務端(Server)存在,Bound Service允許其他組件綁定這個服務,並且發送請求,接受響應,甚至進行進程間通信(IPC),Bound Service通常依賴於其他應用程序組件,並且不會無限期運行下去。
(有一點我聲明一下,就是這些名詞我沒法翻譯,每個人的理解都不一樣,我乾脆就不翻譯了,知道是這麼個意思就行了。)
2,基礎知識
要創建一個Bound Service:
首先需要繼承Service或其子類,這樣纔算是一個Service
其次需要覆寫onBind()方法,這樣纔算是一個Bound Service
打開API文檔:
在Service這個基類裏這個方法是抽象方法,需要返回一個實現了IBinder接口的類的對象,這個接口就是聲明瞭客戶端可以和Service進行通信。到下面找到更爲詳細的解釋:
這個返回的IBinder對象着實需要花點時間去理解,要實現一個Bound Service,最重要的方法就是這個。文檔裏提到一點:
Multiple clients can connect to the service at once. However, the system calls your service's onBind() method to retrieve the IBinder only when the first client binds. The system then delivers the same IBinder to any additional clients that bind, without calling onBind() again.
可以有多個客戶端同時連接這個Service,但是onBind()方法只會調用一次,返回的也只會有一個IBinder對象,所有連接到這個Service的客戶端都是得到這個相同的IBinder對象。
要綁定一個Service,客戶端可以調用
boolean bindService (Intent service, ServiceConnection conn, int flags)
public class LocalService extends Service {
// Binder given to clients
private final IBinder mBinder = new LocalBinder();
// Random number generator
private final Random mGenerator = new Random();
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
LocalService getService() {
// Return this instance of LocalService so clients can call public methods
return LocalService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/** method for clients */
public int getRandomNumber() {
return mGenerator.nextInt(100);
}
}
找到Binder在自己定義的類LocalBinder中定義了一個方法:getService()。再看一下客戶端的代碼:public class BindingActivity extends Activity { LocalService mService; boolean mBound = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override protected void onStart() { super.onStart(); // Bind to LocalService Intent intent = new Intent(this, LocalService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); // Unbind from the service if (mBound) { unbindService(mConnection); mBound = false; } } /** Called when a button is clicked (the button in the layout file attaches to * this method with the android:onClick attribute) */ public void onButtonClick(View v) { if (mBound) { // Call a method from the LocalService. // However, if this call were something that might hang, then this request should // occur in a separate thread to avoid slowing down the activity performance. int num = mService.getRandomNumber(); Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show(); } } /** Defines callbacks for service binding, passed to bindService() */ private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { // We've bound to LocalService, cast the IBinder and get LocalService instance LocalBinder binder = (LocalBinder) service; mService = binder.getService(); mBound = true; } @Override public void onServiceDisconnected(ComponentName arg0) { mBound = false; } }; }
從onServiceConnected()回調方法中拿到了Service,並賦值給了局部變量,在onStart()方法中調用bindService()綁定Service。
public class MessengerService extends Service {
/** Command to the service to display a message */
static final int MSG_SAY_HELLO = 1;
/**
* Handler of incoming messages from clients.
*/
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO:
Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
}
/**
* Target we publish for clients to send messages to IncomingHandler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());
/**
* When binding to the service, we return an interface to our messenger
* for sending messages to the service.
*/
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
return mMessenger.getBinder();
}
}
在這個Service中有個內部類,IncomingHandler繼承Handle,並且覆寫了handleMessage()方法。這有牽扯到一個問題:什麼是Handle?
A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue
今天重點不是這個Handler.
public class ActivityMessenger extends Activity {
/** Messenger for communicating with the service. */
Messenger mService = null;
/** Flag indicating whether we have called bind on the service. */
boolean mBound;
/**
* Class for interacting with the main interface of the service.
*/
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the object we can use to
// interact with the service. We are communicating with the
// service using a Messenger, so here we get a client-side
// representation of that from the raw IBinder object.
mService = new Messenger(service);
mBound = true;
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mService = null;
mBound = false;
}
};
public void sayHello(View v) {
if (!mBound) return;
// Create and send a message to the service, using a supported 'what' value
Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onStart() {
super.onStart();
// Bind to the service
bindService(new Intent(this, MessengerService.class), mConnection,
Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
}
我用紅色標記了一些代碼,