2012-02-20 35 views
12

Tôi có một ứng dụng Android có liên quan đến dịch vụ liên tục (khi đã bắt đầu với startService()).Dọn dẹp ràng buộc/không liên kết với Dịch vụ trong Đơn đăng ký

Dịch vụ là một phần không thể tách rời của ứng dụng và do đó được sử dụng trong hầu hết mọi Hoạt động. Do đó tôi muốn liên kết với dịch vụ chỉ một lần (thay vì ràng buộc/hủy liên kết trong mọi Hoạt động) và giữ liên kết trong suốt thời gian tồn tại của ứng dụng của tôi.

Tôi đã mở rộng từ Application và liên kết với dịch vụ trong Application#onCreate(). Tuy nhiên bây giờ tôi có vấn đề mà tôi không biết khi nào ứng dụng của tôi tồn tại kể từ khi Application#onTerminate() không bao giờ được gọi là, xem javadoc:

Phương pháp này là để sử dụng trong môi trường quá trình mô phỏng. Nó sẽ không bao giờ được gọi trên thiết bị Android sản xuất, nơi các quá trình được xóa bằng cách đơn giản giết chúng; không có mã người dùng (bao gồm cả gọi lại này) là được thực thi khi làm như vậy.

Vậy làm thế nào để tôi hủy liên kết khỏi dịch vụ bị ràng buộc trong Ứng dụng?

Trả lời

12

Tôi đã giải quyết vấn đề này bằng cách tính các tham chiếu đến ràng buộc dịch vụ trong Application. Mỗi Activity phải gọi acquireBinding() trong các phương thức onCreate() của họ và gọi releaseBinding() trong onDestroy(). Nếu bộ đếm tham chiếu đạt đến 0 thì ràng buộc được giải phóng.

Dưới đây là một ví dụ:

class MyApp extends Application { 
    private final AtomicInteger refCount = new AtomicInteger(); 
    private Binding binding; 

    @Override 
    public void onCreate() { 
     // create service binding here 
    } 

    public Binding acquireBinding() { 
     refCount.incrementAndGet(); 
     return binding; 
    } 

    public void releaseBinding() { 
     if (refCount.get() == 0 || refCount.decrementAndGet() == 0) { 
      // release binding 
     } 
    } 
} 

// Base Activity for all other Activities 
abstract class MyBaseActivity extend Activity { 
    protected MyApp app; 
    protected Binding binding; 

    @Override 
    public void onCreate(Bundle savedBundleState) { 
     super.onCreate(savedBundleState); 
     this.app = (MyApp) getApplication(); 
     this.binding = this.app.acquireBinding(); 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     this.app.releaseBinding(); 
    } 
} 
+0

Dịch vụ của bạn tồn tại như thế nào để xoay màn hình? –

+1

Ý của bạn là gì? Dịch vụ trong Android không có giao diện người dùng nên nó vẫn tiếp tục chạy. Trong trường hợp này, Dịch vụ đã được bắt đầu trước đó với 'context.startService()' và được đánh dấu dính sao cho nó chạy cho đến khi nó được dừng lại một cách thủ công hoặc tự dừng lại. –

+0

Tôi hiểu. Tôi đã nghĩ rằng việc giải phóng ràng buộc sẽ ngăn chặn dịch vụ, nhưng không phải trong trường hợp dịch vụ lai này. Các ràng buộc được phát hành để tránh một kết nối dịch vụ bị rò rỉ. –

4

Từ câu trả lời của Sven:

tôi giải quyết vấn đề này bằng cách đếm các tham chiếu đến các dịch vụ ràng buộc trong Đơn. Mỗi Hoạt động phải gọi phương thức obtainBinding() trong các phương thức onCreate() của họ và gọi releaseBinding() trong onDestroy(). Nếu bộ đếm tham chiếu đạt đến số không, thì ràng buộc là được giải phóng.

Tôi đồng ý, NHƯNG bạn không nên làm điều đó trong onDestroy - điều đó thường sẽ không được gọi.

Thay vào đó, tôi đề nghị như sau (dựa trên mẫu mã của bạn) ...

// Base Activity for all other Activities 
abstract class MyBaseActivity extend Activity { 
    protected MyApp app; 
    protected Binding binding; 

    @Override 
    public void onCreate(Bundle savedBundleState) { 
     super.onCreate(savedBundleState); 
     this.app = (MyApp) getApplication(); 
     this.binding = this.app.acquireBinding(); 
    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 
     // Pre-HC, activity is killable after this. 
     if ((11 > Build.VERSION.SDK_INT) && (isFinishing())) 
      onFinishing(); 
    } 

    @Override 
    protected void onStop() { 
     super.onStop(); 
     if ((10 < Build.VERSION.SDK_INT) && (isFinishing())) 
      onFinishing(); 
    } 

    protected void onFinishing() { 
     // Do all activity clean-up here. 
     this.app.releaseBinding();   
    } 
} 

NHƯNG, sử dụng của tôi isFinishing() chỉ là một suy nghĩ - Tôi không chắc chắn rằng nó là đáng tin cậy. Có lẽ onPause/onStop được gọi với isFinishing() false, nhưng sau đó hoạt động bị giết - và releaseBinding của bạn() không bao giờ được gọi.

Nếu bạn thoát khỏi kiểm tra isFinishing, tôi nghĩ bạn cần di chuyển cuộc gọi obtainBinding() từ onCreate sang onStart/onResume (tùy thuộc vào phiên bản sdk), để đảm bảo rằng số lượng ref của bạn không bị rối tung lên.

Ai biết rằng việc phát hành dịch vụ của ứng dụng của bạn sẽ rất phức tạp!

+0

Cảm ơn bạn đã làm rõ. Tôi sẽ xem xét điều này. Tôi cũng có ấn tượng rằng giải pháp của tôi không đáng tin cậy. –

2

Hoàn toàn có cần thiết trong trường hợp này không? Ứng dụng này cũng bị giết. Tôi đã cố gắng thực hiện một ứng dụng mẫu làm điều này mà không cần unbinding và nó có vẻ hoạt động đúng.

+0

Nếu bạn không hủy liên kết, bạn sẽ thấy lỗi "kết nối dịch vụ bị rò rỉ" trong nhật ký. –

Các vấn đề liên quan