2013-09-02 59 views
8

Tôi đang cố gắng sử dụng Dịch vụ trong Android đối với một số thao tác cơ sở dữ liệu cơ bản, nhưng vì lý do nào đó mà tôi nhận được một Activity đã làm rò rỉ lỗi ServiceConnection. Tôi sẽ đăng đầy đủ Logcat readout ở phía dưới.ServiceConnectionLeaked trong Android

Tôi phải sử dụng cùng một dịch vụ trong nhiều hoạt động, vì vậy tôi đã tạo một Lớp cha để xử lý tất cả các tác vụ dịch vụ. Có vẻ như sau:

private MyInterface child; 

public void onCreate(Bundle savedInstanceState, MyInterface child){ 
    super.onCreate(savedInstanceState); 

    doBindService(); 
} 

public void onResume(){ 
    super.onResume(); 

    doBindService(); 
} 

protected void onPause(){ 
    super.onPause(); 

    doUnbindService(); 
} 

private boolean bound; 
private boolean binding; 

ServiceConnection Connection = new ServiceConnection(){ 

    //called when the service is connected 
    @Override 
    public void onServiceConnected(ComponentName name, IBinder service) { 
     Log.d(LOGTAG, "Bound to Service"); 
     bound = true; 
     binding = false; 
     toServiceMessenger = new Messenger(service); 
     while(!commandsForService.isEmpty()){ 
      sendToService(commandsForService.poll()); 
     } 
    } 

    //called when the service is disconnected 
    @Override 
    public void onServiceDisconnected(ComponentName name) { 
     Log.d(LOGTAG, "Unboud from Service"); 
     bound = false; 
     binding = false; 
     toServiceMessenger = null; 
    } 
}; 

private boolean doBindService(){ 
    Log.d(LOGTAG, "Attempting to Bind to Service"); 
    if(!bound && !binding){ 
     binding = true; 
     bindService(new Intent(this, global.FetchService.class), Connection, Context.BIND_AUTO_CREATE); 
    } 
    return bound; 
} 

private void doUnbindService(){ 
    Log.d(LOGTAG, "Attempting to Unbind from Service"); 
    if(bound && !binding){ 
     binding = true; 
     unbindService(Connection); 
    } 
} 

public void sendToService(Message msg){ 
    if(bound){ 
     sendMessageToService(msg); 
    } 
    else{ 
     commandsForService.add(msg); 
    } 
} 

private void sendMessageToService(Message msg){ 
    if(bound){ 
     msg.replyTo = fromServiceMessenger; 
     try { 
      toServiceMessenger.send(msg); 
     } catch (RemoteException e) { 
      Log.d(LOGTAG, "RemoteException communicating with service"); 
     } 
    } 
    else{ 
     Log.d(LOGTAG, "Error: toServiceMessenger null while bound"); 
    } 
} 

Ý tưởng là hoạt động con sẽ không bao giờ cần phải lo lắng về việc kết nối với dịch vụ hay không, Superclass sẽ chăm sóc lấy dữ liệu dịch vụ và quay lại trẻ.

Các điểm Logcat doBindService() trong onCreate() -> bindService (new Intent (this, global.FetchService.class), Connection, Context.BIND_AUTO_CREATE); là dòng gây ra lỗi. Tuy nhiên, dịch vụ chỉ rò rỉ sau khi hoạt động đã chạy và hiển thị trong hơn 15 giây, vì vậy tôi không nghĩ rằng onCreate() nên được gọi.

Đây là Logcat:

09-02 09:25:40.635: E/ActivityThread(5963): Activity childActivity has leaked ServiceConnection [email protected] that was originally bound here 
09-02 09:25:40.635: E/ActivityThread(5963): android.app.ServiceConnectionLeaked: Activity childActivity has leaked ServiceConnection [email protected] that was originally bound here 
09-02 09:25:40.635: E/ActivityThread(5963):  at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:1055) 
09-02 09:25:40.635: E/ActivityThread(5963):  at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:949) 
09-02 09:25:40.635: E/ActivityThread(5963):  at android.app.ContextImpl.bindService(ContextImpl.java:1472) 
09-02 09:25:40.635: E/ActivityThread(5963):  at android.app.ContextImpl.bindService(ContextImpl.java:1464) 
09-02 09:25:40.635: E/ActivityThread(5963):  at android.content.ContextWrapper.bindService(ContextWrapper.java:394) 
09-02 09:25:40.635: E/ActivityThread(5963):  at superClass.doBindService(FetchActivity.java:253) 
09-02 09:25:40.635: E/ActivityThread(5963):  at superClass.onCreate(FetchActivity.java:61) 
09-02 09:25:40.635: E/ActivityThread(5963):  at childActivity.onCreate(Showcase_Activity.java:37) 
09-02 09:25:40.635: E/ActivityThread(5963):  at android.app.Activity.performCreate(Activity.java:5066) 
09-02 09:25:40.635: E/ActivityThread(5963):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1101) 
09-02 09:25:40.635: E/ActivityThread(5963):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2311) 
09-02 09:25:40.635: E/ActivityThread(5963):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2391) 
09-02 09:25:40.635: E/ActivityThread(5963):  at android.app.ActivityThread.access$600(ActivityThread.java:151) 
09-02 09:25:40.635: E/ActivityThread(5963):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1335) 
09-02 09:25:40.635: E/ActivityThread(5963):  at android.os.Handler.dispatchMessage(Handler.java:99) 
09-02 09:25:40.635: E/ActivityThread(5963):  at android.os.Looper.loop(Looper.java:155) 
09-02 09:25:40.635: E/ActivityThread(5963):  at android.app.ActivityThread.main(ActivityThread.java:5493) 
09-02 09:25:40.635: E/ActivityThread(5963):  at java.lang.reflect.Method.invokeNative(Native Method) 
09-02 09:25:40.635: E/ActivityThread(5963):  at java.lang.reflect.Method.invoke(Method.java:511) 
09-02 09:25:40.635: E/ActivityThread(5963):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028) 
09-02 09:25:40.635: E/ActivityThread(5963):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:795) 
09-02 09:25:40.635: E/ActivityThread(5963):  at dalvik.system.NativeStart.main(Native Method) 

Bất kỳ trợ giúp sẽ được đánh giá cao.

+0

Liệu ServiceConnectionLeaked xảy ra sau khi bạn rời khỏi childActivity? Bạn có thể đặt các câu lệnh Log ngay lập tức sau bindService và unbindService để đảm bảo chúng được gọi là các cặp phù hợp không? –

+0

Có thể thử gọi doUnbindService() * trước khi gọi super.onPause() (trong phương thức onPause() của bạn)? – Ponkadoodle

Trả lời

9

Khi bạn gọi số doBindService() trong số onCreate(), bạn nên thêm số UnbindService() vào số onDestroy().

Nó phù hợp với tôi.

+0

Xin lỗi tôi đã phản hồi quá lâu. Đối với những người đến trong tương lai: giải pháp là các cuộc gọi tới doBindService() và doUnbindService() phải được nhân đôi trong vòng đời của Activity Android.Bởi vì ràng buộc với một dịch vụ có thể mất một thời gian, nên thực hiện trong onCreate() và onDestroy(). Tôi đã làm điều đó trong onResume() và onPause() vì tôi đã hoang tưởng về vòng đời của Android. – MrMannWood

3

Bạn đang gọi điện thoại doBindService() trong cả onCreate()onResume(), cố gắng gọi đó là chỉ trong onResume() để phù hợp với cuộc gọi của bạn để doUnbindService() trong onPause()

+0

Tôi chỉ cố gắng này và nó đã không làm việc, Logcat bây giờ trỏ đến doBindService trong onResume(). Tôi sẽ không mong đợi đây là một vấn đề anyway, như booleans của tôi nên chắc chắn rằng cuộc gọi không xảy ra cả hai lần. doBindService có cả hai để đảm bảo rằng a) dịch vụ luôn được kết nối khi hoạt động hiển thị và b) dịch vụ kết nối nhanh chóng khi hoạt động này được tạo ra – MrMannWood

1

Bạn cần phải sử dụng tài liệu tham khảo tốt cho các Hoạt động getActivity() trả lại hiện tại một, và bạn cần phải unbind trên một trong đó đã làm các ràng buộc

dưới đây là cách tôi cố định vấn đề:

private Activity mActivity; 
    @Override 
    public void onStart() { 
     super.onStart(); 
     if (!mBound) { 
      startService(); 
      mActivity = getActivity(); 
     } 
    } 

    @Override 
    public void onStop() { 
     super.onStop(); 
     if (mBound && mActivity != null) { 
      mActivity.unbindService(mServiceConnection); 
      mActivity = null; 
     } 
    } 
1

Bạn nhận được lỗi này vì dịch vụ bạn liên kết với hoạt động không bị dừng khi hoạt động đó bị hủy. Vì vậy, do dịch vụ của bạn vẫn còn tồn tại trong bộ nhớ và tiêu thụ tài nguyên, mà không làm gì cả.

Để giải quyết vấn đề này gọi doBindService() trong onCreate()doUnbindService() trong onDestroy()