2011-06-03 15 views
6

निम्नलिखित पर विचार करें: मुझे Service मिल गया है, जो AsyncTask में डीबी में लिखता है। और मेरी गतिविधि डीबी से डेटा पढ़ती है (सादगी के लिए यूआई थ्रेड पर विचार करें)। मैं SQLiteOpenHelper का उपयोग कर डीबी तक पहुंचता हूं। मैं Application onCreate() में एकल उदाहरण बना देता हूं और फिर इसे सेवा और गतिविधि में प्राप्त करता हूं। क्या कोई संभावना है कि मुझे अपना डीबी 'मृत लॉक' मिलेगा? पहले, मैंने इस तरह के संचालन के लिए ContentProvider का उपयोग किया था। हालांकि, यह एकल SQLiteOpenHelper उदाहरण का उपयोग करने पर आधारित है, मैंने ContentProvider को छोड़कर अपनी परियोजना को सरल बनाने का निर्णय लिया।SQLite डीबी एकाधिक धागे से

public class App extends Application { 

    private OpenHelper openHelper; 

    @Override 
    public void onCreate(){ 
     super.onCreate(); 
      openHelper=new OpenHelper(); 
    } 

     public OpenHelper getHelper(){ 
      return openHelper; 
     } 
} 

गतिविधि में:

कोड पर विचार करें

OpenHelper helper=(App)getApplication().getHelper(); 
SQLiteDatabase db=helper.getReadableDatabase(); 
// Do reading 

और serice अंदर, अलग थ्रेड में:

OpenHelper helper=(App)getApplication().getHelper(); 
SQLiteDatabase db=helper.getWritableDatabase(); 
//Do writing 

यह सुरक्षित होगा?

UPDThis समाधान हो सकता है, लेकिन यह सुनिश्चित नहीं है कि इसका उपयोग कैसे किया जाए।

उत्तर

0

अच्छा सवाल। मेरा पहला विचार यह सुरक्षित नहीं होगा। हालांकि, SQLite docs के अनुसार, SQLite का उपयोग 3 मोड में किया जा सकता है। डिफ़ॉल्ट मोड "धारावाहिक" मोड है:

सीरियलाइज्ड। धारावाहिक मोड में, SQLite सुरक्षित रूप से कोई प्रतिबंध नहीं

साथ एक से अधिक थ्रेड द्वारा इस्तेमाल किया जा सकता तो मैं इस मान यह एंड्रॉयड पर धारावाहिक मोड में संकलित है।

2

मेरी शर्त: यह सुरक्षित नहीं है।

सुरक्षित स्थिति में रहने के लिए आपको SQL लेनदेन का उपयोग करना चाहिए। beginTransaction() या beginTransactionNonExclusive() के साथ शुरू करें और endTransaction() के साथ समाप्त करें। Like shown here

+0

startTransactionNonExclusive() मुझे त्रुटि देता है कि यह उपरोक्त api11 के लिए है। लेकिन मेरे ऐप्स min api 10 है। सरल मोड के साथ स्क्लाइट का उपयोग करने का कोई अन्य तरीका? –

1

यह मेरा समाधान है मैं सभी db पहुँच

public class DBFunctions { 
// ... 
private static Object lockdb = new Object(); 


/** 
* Do something using DB 
*/ 
public boolean doInsertRecord(final RecordBean beanRecord) { 
    // ... 
    boolean success = false; 

    synchronized (lockdb) { 
       // ... 
       // 
       // here ... the access to db is in exclusive way 
       // 

       // ... 
     final SQLiteStatement statement = db.compileStatement(sqlQuery); 

     try { 
      // execute ... 
      statement.execute(); 
      statement.close(); 

      // ok 
      success = true; 
     } catch (Exception e) { 
      // error 
      success = false; 
     } 
      } 

     return success; 
    } 

}

मैं ASYNC कार्य का उपयोग कर tryed syncronize करने के लिए एक वर्ग और एक निजी स्थिर वस्तु बनाया है और यह ठीक काम करता है। मुझे उम्मीद है कि समस्या को हल करने का सही तरीका है।

कोई अन्य सुझाव ???

+0

एक ही समय में तीन AsyncTasks चल रहा है, सभी एक पंक्ति में कई पंक्तियों को सम्मिलित करते हैं। (सभी एक ही टेबल पर लिखते हैं।) ऐसा प्रतीत होता है कि कार्य कतार और इस प्रकार कोई त्रुटि नहीं फेंक दी गई है। यह समाधान मेरे लिए काम करता है। फिर भी मुझे आश्चर्य है कि यह समाधान मृत-लॉक सुरक्षित है या नहीं। कोई राय? – BenjaminButton

+0

कुछ और परीक्षण डेटाबेस लॉक त्रुटियों के बाद फिर से दिखाई दिया ... – BenjaminButton

0

बस यह देखा कि मैं कुछ और ढूंढ रहा था। यह समस्या ऐसा लगता है कि इसे ContentProvider का उपयोग करके कुशलता से हल किया जाएगा। इस तरह गतिविधि और सेवा दोनों ही सामग्री प्रदाता का उपयोग कर सकते हैं और यह डीबी विवाद के मुद्दों का ख्याल रखेगा।

7

देर से, देर से उत्तर। तुम बिल्कुल ठीक हो वास्तव में ऐसा करने का यह सही तरीका है। मेरा ब्लॉग पोस्ट देखें: http://touchlabblog.tumblr.com/post/24474750219/single-sqlite-connection/। यहां मेरी प्रोफाइल के माध्यम से खोदना। इसके कई उदाहरण हैं। ContentProvdier केवल बहुत अधिक ओवरहेड है और इसकी आवश्यकता नहीं है जब तक कि आप अपने ऐप के बाहर डेटा साझा नहीं कर लेते। लेन-देन चीजों को गति देने के लिए अच्छे होते हैं और (जाहिर है) स्थिरता में सुधार करते हैं, लेकिन इसकी आवश्यकता नहीं होती है।

बस अपने ऐप में एक स्क्लाइट ओपेनहेल्पर का उपयोग करें और आप सुरक्षित हैं।

+0

ब्लॉग पोस्ट – seb

+0

@seb संपादित उत्तर है। कई महीनों पहले ब्लॉग हटाया। स्क्लाइट लॉकिंग पोस्ट को भी देखें: http://touchlabblog.tumblr.com/post/24474398246/android-sqlite-locking। वे यहां कुंजी हैं एंड्रॉइड जावा-भूमि में आपके लिए हुड के नीचे थ्रेड लॉकिंग करता है, लेकिन केवल एक ही उदाहरण पर। एकाधिक एक दूसरे को पकड़ लेंगे। इसके अलावा, पोस्ट में यह कहता है कि यूबी थ्रेड में डीबी पढ़ता है। कृपया ध्यान दें: ऐसा मत करो। कभी। –

+0

@ केविन गॉलिगन मैंने SQLiteDatabase और हेल्पर के स्रोत के माध्यम से खोला है और मुझे विश्वास है कि आप गलत हैं। डेटाबेस ऑब्जेक्ट एक SQLiteStatement ऑब्जेक्ट बनाता है जो बदले में SQLiteSession का उपयोग करता है, प्रत्येक थ्रेड का अपना SQLite सत्र होगा। यह विशेष रूप से SQLiteSession javadoc में क्लास थ्रेड सुरक्षित नहीं है। उत्सुकता से आप यह क्या कहते हैं, क्योंकि मैं वास्तव में आपको सही होना चाहता हूं ... – schwiz

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