我在远程服务中遇到回调问题,注册回调轮换后会导致活动泄漏。你能给我一些建议吗?我做错了什么。
IRemoteApi.aidl
import com.example.remoteservice.IRemoteListener;
interface IRemoteApi{
void addListener(IRemoteListener listener);
void removeListener(IRemoteListener listener);
void sendRequest(String msg);
}
IRemoteListener.aidl
interface IRemoteListener {
void onMessage(String text);
}
远程服务.java
public class RemoteService extends Service {
private static final String TAG = RemoteService.class.getSimpleName();
final RemoteCallbackList<IRemoteListener> mCallbacks = new RemoteCallbackList<IRemoteListener>();
@Override
public void onCreate() {
super.onCreate();
Log.e(TAG, "Create service...");
}
@Override
public void onDestroy() {
super.onDestroy();
mCallbacks.kill();
}
private void dumpMethod(String msg){
if(msg.equals("OK")){
final int N = mCallbacks.beginBroadcast();
for (int i=0; i<N; i++) {
try {
mCallbacks.getBroadcastItem(i).onMessage("Voila!");
} catch (RemoteException e) {}
}
mCallbacks.finishBroadcast();
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private IRemoteApi.Stub mBinder = new IRemoteApi.Stub() {
@Override
public void addListener(IRemoteListener listener) throws RemoteException {
if (listener != null) mCallbacks.register(listener);
}
@Override
public void removeListener(IRemoteListener listener) throws RemoteException {
if (listener != null) mCallbacks.unregister(listener);
}
@Override
public void sendRequest(String msg) throws RemoteException {
dumpMethod(msg);
}
};
}
MainActivity.java
public class MainActivity extends ActionBarActivity {
private static final String TAG = MainActivity.class.getSimpleName();
IRemoteApi mService;
boolean isBound = false;
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IRemoteApi.Stub.asInterface(service);
isBound = true;
Log.e("merhold", "Bound to service");
try {
mService.addListener(serviceListener);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getApplicationContext().startService(new Intent(RemoteService.class.getName()));
getApplicationContext().bindService(new Intent(RemoteService.class.getName()), mServiceConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
if(isBound){
try {
mService.removeListener(serviceListener);
getApplicationContext().unbindService(mServiceConnection);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
public void sendRequest(View view) {
try {
mService.sendRequest("OK");
} catch (RemoteException e) {
e.printStackTrace();
}
}
private IRemoteListener serviceListener = new IRemoteListener.Stub(){
@Override
public void onMessage(String text) throws RemoteException {
Log.e(TAG, "Message from listener: "+text);
}
};
}
因为有两个进程,所以也涉及两个垃圾收集器。
服务和客户端垃圾收集器。该服务处理小型IBinder
对象(IRemoteListener)对于快速垃圾收集来说并不那么重要。来自客户
这些 IBinder 对象持有对一个大活动的引用。
在服务完成垃圾收集之前,无法对 Activity 进行垃圾收集
IBinder 对象,因此在发生这种情况之前它将被泄漏。解决方案是改变
侦听器进入静态内部类。如果您想访问活动中的某些内容
你必须使用弱引用。
这是 Dianne Hackborn 的相关问题和解释;https://stackoverflow.com/a/12206516/1035854 https://stackoverflow.com/a/12206516/1035854
一些代码:
private static class MyRemoteListener extends IRemoteListener.Stub {
private final WeakReference<Activity> mWeakActivity;
public MyRemoteListener(Activity activity) {
mWeakActivity = new WeakReference<Activity>(activity);
}
@Override
public void onMessage(String text) throws RemoteException {
Activity activity = mWeakActivity.get();
if (activity != null) {
// ((MainActivity)activity).handleOnMessage(text);
}
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)