問題描述
我目前在我的應(yīng)用中使用 2 項服務(wù):
I am currently using 2 services in my app:
1:LocationService,主要是嘗試本地化用戶,目標(biāo)是僅在應(yīng)用處于前臺時才保持活動狀態(tài).
1: LocationService, basically trying to localize the user, and aims to stay alive only when the app is on foreground.
2:XmppService,它初始化與 xmpp 服務(wù)器的連接、接收消息、發(fā)送消息、注銷...并旨在保持活動狀態(tài)直到用戶注銷.
2: XmppService, which init the connection with the xmpp server, receive messages, send it, logout ... and aims to stay alive until the user logout.
我已經(jīng)閱讀了很多文檔,但我無法說清楚.
I've been reading quite a lot of documentation, but I just can't make it clear.
當(dāng)我嘗試存儲 LocationServiceBinder 的引用時,我遇到了泄漏,它用于調(diào)用我的服務(wù)函數(shù)(使用 AIDL 接口).Xmpp 也一樣.當(dāng)我解除綁定時,有時會出現(xiàn) ANR(這似乎與我的綁定/解除綁定異常完成的事實有關(guān),onResume、onRestart ...).
I'm having Leaks when I try to store reference of LocationServiceBinder, which is used to call my service functions (using AIDL interfaces). Same for Xmpp. When I unbind, I get sometimes ANR (which look like to be linked with the fact that my bind/unbind are weirdly done, onResume, onRestart ...).
所有系統(tǒng)都在工作,但我確信這不是正確的做法,我很樂意跟隨有經(jīng)驗的人回到部隊的右側(cè)!:)
All the system is working, but I'm sure it is not the right way to do it, and please I would love to follow experienced people to come back in the right side of the force ! :)
干杯
更新
我的位置服務(wù)在應(yīng)用啟動時綁定,以盡可能快地獲取用戶的位置:
My Location Service is bind at the app launch to get as fast as possible the user's position :
if(callConnectService == null) {
callConnectService = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder binder) {
locationServiceBinder = LocationServiceBinder.Stub.asInterface(binder);
try {
global.setLocationBinder(locationServiceBinder);
global.getLocationBinder().startLocationListener();
} catch (Exception e){
Log.e(TAG, "Service binder ERROR");
}
}
public void onServiceDisconnected(ComponentName name) {
locationServiceBinder = null;
}
};
}
/* Launch Service */
aimConServ = new Intent(this, LocationService.class);
boolean bound = bindService(aimConServ,callConnectService,BIND_AUTO_CREATE);
我的 Xmpp 服務(wù)在用戶登錄時啟動:
My Xmpp Service is launched when the user log in :
callConnectService = new ServiceConnection() {
callConnectService = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder binder) {
try {
Log.d(TAG, "[XMPP_INIT] Complete.");
global.setServiceBinder(ConnectionServiceBinder.Stub.asInterface(binder));
//Connect to XMPP chat
global.getServiceBinder().connect();
} catch (Exception e){
Log.e(TAG, "Service binder ERROR ");
e.printStackTrace();
}
}
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG, "Service binder disconnection ");
}
};
/* Launch Service */
Intent aimConServ = new Intent(MMWelcomeProfile.this, XmppService.class);
bound = bindService(aimConServ,callConnectService,Context.BIND_AUTO_CREATE);
并在每個 Activity 上取消綁定:
and unbind on each Activity :
if (callConnectService != null){
unbindService(callConnectService);
callConnectService = null;
}
推薦答案
在谷歌官方開發(fā)指南中并沒有詳細記載,Context.bindService() 實際上是一個異步調(diào)用.這就是為什么 ServiceConnection.onServiceConnected() 被用作回調(diào)方法的原因,意味著不會立即發(fā)生.
It hasn't been well-documented in Google's official dev guide, Context.bindService() is actually an asynchronous call. This is the reason why ServiceConnection.onServiceConnected() is used as a callback method, means not happened immediately.
public class MyActivity extends Activity {
private MyServiceBinder myServiceBinder;
protected ServiceConnection myServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
myServiceBinder = (MyServiceBinderImpl) service;
}
... ...
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// bindService() is an asynchronous call. myServiceBinder is resoloved in onServiceConnected()
bindService(new Intent(this, MyService.class),myServiceConnection, Context.BIND_AUTO_CREATE);
// You will get a null point reference here, if you try to use MyServiceBinder immediately.
MyServiceBinder.doSomething(); // <-- not yet resolved so Null point reference here
}
}
解決方法是在 myServiceConnection.onServiceConnected() 中調(diào)用 MyServiceBinder.doSomething(),或者通過一些用戶交互(例如按鈕單擊)執(zhí)行 MyServiceBinder.doSomething(),因為在調(diào)用 bindService() 之后和系統(tǒng)獲取之前的滯后myServiceBinder 的引用很快.只要你不立即使用它就可以了.
A workaround is call MyServiceBinder.doSomething() in myServiceConnection.onServiceConnected(), or perform MyServiceBinder.doSomething() by some user interaction (e.g. button click), as the lag after you call bindService() and before system get a reference of myServiceBinder is quite soon. as long as you are not using it immediately, you should be just fine.
查看這個 SO 問題CommonsWare 的答案了解更多詳情.
Check out this SO question CommonsWare's answer for more details.
這篇關(guān)于Android 上服務(wù)的良好做法的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!