2012-02-20 30 views
12

मेरे पास एक एंड्रॉइड एप्लिकेशन है जो एक सतत सेवा के लिए बाध्यकारी है (एक बार startService() के साथ शुरू हुआ)।किसी एप्लिकेशन में किसी सेवा में स्पष्ट रूप से बाध्यकारी/अनबाइंडिंग

सेवा एप्लिकेशन का एक अभिन्न अंग है और इस प्रकार लगभग हर गतिविधि में उपयोग किया जाता है। इसलिए मैं केवल एक बार सेवा (बाध्यकारी/बाध्यकारी की बजाय प्रत्येक गतिविधि में) से जुड़ना चाहता हूं और अपने आवेदन के जीवनकाल के दौरान बाध्यकारी रखना चाहता हूं।

मैं Application से बढ़ा हूं और Application#onCreate() में सेवा से जुड़ गया हूं।

इस विधि नकल करते प्रक्रिया वातावरण में प्रयोग के लिए है: हालांकि मैं अब समस्या यह है कि मैं जब अपने आवेदन Application#onTerminate() के बाद से मौजूद है कभी नहीं कहा जाता है पता नहीं है है, जावाडोक देखते हैं। यह कभी भी उत्पादन एंड्रॉइड डिवाइस पर नहीं बुलाया जाएगा, जहां प्रक्रियाओं को आसानी से मार कर हटा दी जाती है; कोई उपयोगकर्ता कोड (इस कॉलबैक सहित) ऐसा करने पर निष्पादित किया गया है।

तो मैं आवेदन में बंधे सेवा से कैसे साफ हो सकता हूं?

उत्तर

12

मैंने Application में बाध्यकारी सेवा के संदर्भों की गणना करके इस समस्या को हल किया। प्रत्येक Activity को को onCreate() विधियों में कॉल करना होगा और releaseBinding() पर onDestroy() पर कॉल करना होगा। यदि संदर्भ काउंटर शून्य तक पहुंचता है तो बाध्यकारी जारी किया जाता है।

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

आपकी सेवा स्क्रीन रोटेशन कैसे टिकती है? –

+1

आपका क्या मतलब है? एंड्रॉइड में एक सेवा में यूआई नहीं है इसलिए यह चल रहा है। इस मामले में सेवा को पहले 'context.startService()' के साथ शुरू किया गया था और चिपचिपा चिह्नित किया गया है, इसलिए यह तब तक चलता है जब तक कि यह मैन्युअल रूप से बंद नहीं हो जाता है या स्वयं बंद हो जाता है। –

+0

मैं देखता हूं। मैं सोच रहा था कि बाध्यकारी जारी करने से सेवा बंद हो जाएगी, लेकिन इस हाइब्रिड-सेवा मामले में नहीं। एक लीक सेवा कनेक्शन से बचने के लिए बाध्यकारी जारी किया जाता है। –

4

स्वेन के जवाब से::

यहाँ एक उदाहरण है

मैं सेवा आवेदन में बाध्यकारी के लिए संदर्भ की गणना के द्वारा इस समस्या का समाधान। प्रत्येक गतिविधि को अधिग्रहण बाइंडिंग() को ऑन-क्रेट() विधियों में कॉल करना है और कॉल रिलीज बाइंडिंग() ऑनडेस्ट्राय() में कॉल करना है। यदि संदर्भ काउंटर शून्य तक पहुंचता है तो बाध्यकारी जारी किया जाता है।

मैं सहमत हूं, लेकिन आपको इसे डेस्ट्रॉय में नहीं करना चाहिए - जिसे अक्सर नहीं कहा जाता है। मुझे विश्वास है कि यह विश्वसनीय है नहीं कर रहा हूँ -

इसके बजाय मैं निम्नलिखित (अपने कोड नमूने के आधार पर) ...

// 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();   
    } 
} 

लेकिन, isFinishing के अपने प्रयोग() सिर्फ एक विचार है सुझाव देते हैं। शायद ऑन पॉज़/ऑनस्टॉप को बुलाया जा रहा है फिनिशिंग() झूठी है, लेकिन फिर गतिविधि मारे जाती है - और आपकी रिलीज बाइंडिंग() कभी भी कॉल नहीं होती है।

यदि आप isfinishing जांच से छुटकारा पा रहे हैं तो मुझे लगता है कि आपको अधिग्रहण() एसडीके संस्करण के आधार पर अधिग्रहण() एसडीके संस्करण पर निर्भर करता है (एसडीके संस्करण के आधार पर), ताकि आपकी रेफ गिनती गड़बड़ न हो।

कौन जानता था कि आपके ऐप की सेवा जारी करना इतना जटिल होगा!

+0

स्पष्टीकरण के लिए धन्यवाद। मैं इसे देख लूंगा। मुझे यह भी धारणा है कि मेरा समाधान हर समय विश्वसनीय नहीं है। –

2

इस मामले में बिल्कुल अनिवार्य है? आवेदन वैसे भी मारा जाता है। मैंने बिना किसी बाध्य किए नमूना अनुप्रयोग को कार्यान्वित करने का प्रयास किया और ऐसा लगता है कि यह ठीक से काम करता है।

+0

यदि आप अनबिंड नहीं करते हैं तो आपको लॉग में "लीक सेवा कनेक्शन" त्रुटियां दिखाई देनी चाहिए। –

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^