2011-09-22 13 views
8

मुझे कोई समस्या है और मुझे यकीन नहीं है कि इसे कैसे पहुंचाया जाए। मेरे ऐप में एक गतिविधि में कई AsyncTask एस हैं जो एकल SQLiteOpenHelper तक पहुंचते हैं। मैं onCreate() में सहायक को प्रारंभ और खोलता हूं और मैं इसे onStop() में बंद कर रहा हूं। मैं यह भी जांचता हूं कि इसे onResume() में प्रारंभ किया गया है या नहीं।एंड्रॉइड AsyncTask और SQLite डीबी इंस्टेंस

चूंकि मैंने अपना ऐप प्रकाशित किया है, इसलिए मुझे doInBackground में नल अपवाद के साथ त्रुटियों की संख्या मिली है जहां मैं डीबी सहायक का उपयोग करने का प्रयास करता हूं। मुझे पता है कि ऐसा इसलिए होता है क्योंकि डीबी बंद है (onStop()) doInBackground से ठीक पहले, उचित मेला कहा जाता है।

मेरा सवाल है, मुझे डीबी कनेक्शन कहां बंद करना चाहिए? क्या गतिविधि में डीबी सहायक के एक उदाहरण का उपयोग करना और इसे एकाधिक धागे (AsyncTasks) से एक्सेस करना सही है? या मुझे प्रत्येक AsyncTask के लिए अलग डीबी सहायक उदाहरण का उपयोग करना चाहिए?

यह मेरा गतिविधि का एक सरलीकृत कंकाल है:

public class MyActivity extends Activity{ 
    private DbHelper mDbHelper; 
    private ArrayList<ExampleObject> objects; 

    @Override 
    public void onStop(){ 
     super.onStop(); 
     if(mDbHelper != null){ 
      mDbHelper.close(); 
      mDbHelper = null; 
     } 
    } 

    @Override 
    public void onResume(){ 
     super.onResume(); 
     if(mDbHelper == null){ 
      mDbHelper = new DbHelper(this); 
      mDbHelper.open(); 
     } 
    } 

    @Override 
    public void onCreate(Bundle icicle) { 
     super.onCreate(icicle); 
     DbHelper mDbHelper = new DbHelper(this); 
     mDbHelper.open(); 
    } 

    private class DoSomething extends AsyncTask<String, Void, Void> { 

     @Override 
     protected Void doInBackground(String... arg0) { 
      objects = mDbHelper.getMyExampleObjects(); 
      return null; 
     } 

     @Override 
     protected void onPostExecute(final Void unused){ 
      //update UI with my objects 
     } 
    } 

    private class DoSomethingElse extends AsyncTask<String, Void, Void> { 

     @Override 
     protected Void doInBackground(String... arg0) { 
      objects = mDbHelper.getSortedObjects(); 
      return null; 
     } 

     @Override 
     protected void onPostExecute(final Void unused){ 
      //update UI with my objects 
     } 
    } 
} 

उत्तर

1

आपने बताया कि डीबी बंद करने से पहले आप AsyncTask को रद्द कर देते हैं। लेकिन आपको यह ध्यान रखना चाहिए कि AsyncTask को रद्द करना केवल कार्य को रद्द करने का संकेत देता है और आपको doInBackground() में isCancelled() की जांच करने की आवश्यकता है और डीबी संचालन को रोकने के लिए आवश्यक है।

डीबी बंद करने से पहले, आपको यह सुनिश्चित करने के लिए getStatus() को जांचना होगा कि AsyncTask बंद हो गया है।

+0

तो मूल रूप से मुझे doInBackground में (! IsCancelled) {} ​​का उपयोग करना चाहिए और लूप के अंदर सभी गणना करना चाहिए? – Marqs

+0

हां, और अपने मुख्य थ्रेड में getStatus() को यह सुनिश्चित करने के लिए जांचें कि AsyncTask समाप्त हो गया है। –

+0

ठीक है लेकिन अगर मैं इसे ऑनस्टॉप() में जांचता हूं और यह समाप्त नहीं हुआ है? मैं डीबी कनेक्शन कहां बंद करूंगा? – Marqs

5

यह एक DB Helper उपयोग करने के लिए अच्छा है। समस्या यह है कि जब उपयोगकर्ता ActivityDB छोड़ देता है तो बंद हो जाता है लेकिन AsyncTask अभी भी चल सकता है। इसलिए आपको यह जांचना चाहिए कि DB शून्य नहीं है जब आप इसे एक्सेस करने का प्रयास कर रहे हैं, और यदि यह null है तो इसका अर्थ यह हो सकता है कि आपका Activity नष्ट हो गया था और cancel वह कार्य था।

+0

तेज प्रतिक्रिया के लिए धन्यवाद। मैं यह उल्लेख करना भूल गया कि मुझे कुछ अपवाद भी हैं जो 'अनियमित बयानों के कारण बंद करने में असमर्थ' कह रहे हैं। इसका शायद मतलब है कि मैं ऑन-स्टॉप() में डीबी कनेक्शन को बंद करने का प्रयास करता हूं, जबकि क्वेरी doInBackground() में निष्पादित होती है। मैं डीबी को छूने से पहले AsyncTask को रद्द करता हूं लेकिन मुझे अभी भी यह त्रुटि मिलती है। कोई विचार क्यों हो रहा है? – Marqs

+0

@ ओविडिउ आप आमतौर पर डीबी प्रारंभिकरण और सफाई कोड कहां डालते हैं? (Suppousing एक डीबीहेल्पर कई विचारों से accesed जा रहा है)। –

+0

के रूप में @ बोल्डर ने कहा कि यह इसे –

11

आपको प्रत्येक गतिविधि के लिए डीबी कनेक्शन प्रबंधित करने की आवश्यकता नहीं है। आप इसे इस उदाहरण का उपयोग करके android.app. अनुप्रयोग और डीबी एक्सेस के उदाहरण में कर सकते हैं। कुछ इस तरह:

public class MyApplication extends Application { 

    // Synchronized because it's possible to get a race condition here 
    // if db is accessed from different threads. This synchronization can be optimized 
    // thought I wander if it's necessary 
    public synchronized static SQLiteDatabase db() { 
     if(self().mDbOpenHelper == null) { 
      self().mDbOpenHelper = new MyDbOpenHelper(); 
     } 
     return self().mDbOpenHelper.getWritableDatabase(); 
    } 

    public static Context context() { 
     return self(); 
    } 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     mSelf = this; 
    } 

    private static MyApplication self() { 
     if (self == null) throw new IllegalStateException(); 
     return mSelf; 
    } 

    private MyDbOpenHelper mDbOpenHelper; 

    private static MyApplication mSelf; 
} 

इस तरह आप सुनिश्चित करें कि आप Db हमेशा पहुँचा जा सकता है हो सकता है।

और हाँ, डीबी सहायक का एक उदाहरण होने का एक अच्छा अभ्यास है। डिफ़ॉल्ट रूप से थ्रेड सिंक्रनाइज़ेशन आपके लिए बनाया जाता है।

+0

+1 में रखने के लिए एक अच्छा अभ्यास हो सकता है - यह बहुत दिलचस्प है, मैं इसे देख लूंगा - धन्यवाद! – Marqs

+0

एक और सवाल ... आप डीबी कनेक्शन कहां बंद करेंगे? – Marqs

+0

मैं इसे बंद नहीं करता हूं। आश्चर्य है कि यह वास्तव में जरूरी है। यदि आप इस पर अधिक जानकारी प्राप्त कर सकते हैं तो कृपया साझा करें, यह दिलचस्प है। सोचा कि मैं इस दृष्टिकोण के साथ कभी भी कोई समस्या नहीं सौंपता हूं। –

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