5

मेरे पास एक टुकड़ा है जिसमें एक सूचीदृश्य है।ContentProvider परमाणु कॉल करता है? ऑन पर रोकें, ऑनएक्टिविटी में लोड, पुराने डेटा

ऑनपॉज़() में मैं ContentProvider में सूचीदृश्य की वाई स्क्रॉल स्थिति को सहेज रहा हूं।

रेज़्यूम या एक्टिविटी पर आधारित एक ही टुकड़ा सामग्रीप्रोवाइडर से उस वाई स्क्रॉल स्थिति को पकड़ने और स्क्रॉल स्थिति को पुनर्स्थापित करने के लिए लोडर का उपयोग करता है।

यदि मैं गतिविधि/टुकड़े से बाहर निकलता हूं और उस पर वापस लौटता हूं, तो यह काम करता है, सूचीदृश्य अपने अंतिम खोले गए स्थान पर लौटता है क्योंकि इसे सामग्री प्रोवाइडर पर सहेज दिया गया था। तो कोड 100% ठीक है।

क्या ठीक नहीं है, घुमाव पर डेटा है। पर रोक ठीक है, लेकिन क्रिएटएक्टिविटी के बाद लोड पुराने डेटा को पुनर्प्राप्त करने के परिणामस्वरूप, रोकें से पहले डेटा। इसके परिणामस्वरूप ओल्ड स्थिति में लौटने पर सूचीदृश्य में परिणाम होता है जब उन्होंने पहली बार ऐप खोला था, न कि स्थिति जहां रोटेशन से पहले था।

यह एक स्पष्ट दौड़ की स्थिति की तरह लगता है कि ऑनपॉज़ के दौरान सामग्री प्रदाता को सहेजने पर रोक नहीं है, जिसके परिणामस्वरूप पुराने डेटा को घुमाने के बाद लोड किया जा रहा है।

तो मेरे फ़ोन पर घुमाने की तरह इस

01:31:33.026: ThreadViewerFragment.java(235):onPause Saved(position:Yposition): 59:-74 
01:31:33.256: ThreadViewerFragment.java(194):onActivityCreated 
01:31:33.266: ThreadViewerFragment.java(309):onLoadFinished Load(position:Yposition): 62:-149 //initial load is of old values 
01:31:33.266: ThreadViewerFragment.java(309):onLoadFinished Load(position:Yposition): 62:-149 
01:31:33.596: ThreadViewerFragment.java(309):onLoadFinished Load(position:Yposition): 59:-74 //this is loaded due to notification by the save in onPause which is supposed to be finished before recreating the new fragment??? 

तो आदेश ठीक लग रहा है लग रहा है के बजाय लेकिन स्पष्ट रूप से, यह भरी हुई है पुराने मूल्यों (गतिविधि/टुकड़ा प्रवाह के मामले में एक रेस स्थिति की तरह नहीं दिखता) 59: -74 के केवल सहेजे गए मूल्यों में से।

मैं आसपास के काम के बाद नहीं हूं, मुझे पता है कि saveInstanceState आदि का उपयोग कैसे करें। लेकिन मुझे अपना कोड क्यों दोगुना करना चाहिए, क्या सामग्रीप्रोवाइडर को परमाणु व्यवहार करने के लिए मजबूर करने का कोई तरीका है (जिसे मैंने पहले ही सोचा था?)

संपादित करें: कोड जोड़ना और प्रश्न को थोड़ा बेहतर परिष्कृत करना क्योंकि मैं अभी भी संतुष्ट नहीं हूं कि अगर सामग्री प्रदाता निष्पादित होने पर ब्लॉक को कॉल करता है और/या यदि वे कॉल परमाणु हैं या यदि यह केवल गलतफहमी है तो हम समझने के करीब हैं contentproviders और लोडर के।

onPause में, मैं उत्पाद लिस्टिंग

@Override 
public void onPause() { 
    super.onPause(); 

    Utils.logv("onPause Saved position: " + mLastRead + ", " + mYPos); 

    ContentValues contentValues = new ContentValues(); 
    contentValues.put(ProductsContract.Products.Y_POS, mYpos); 

    int updateCount = getActivity().getContentResolver().update(
       Uri.parse(ProductsContract.Products.CONTENT_URI + "/" + mId), 
       contentValues, null, null); 
} 

मेरे समझते हैं कि कॉल अद्यतन करने के लिए एक अवरुद्ध कॉल होना चाहिए की Y स्थिति बंद बचत कर रहा हूँ, और इससे पहले टुकड़ा नष्ट कर दिया और इससे पहले कि है यह तब होता है नई टुकड़ा रोटेशन

में फिर से शुरू पर मैं अपने लोडर

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

    getLoaderManager().initLoader(PRODUCTS_LOADER_ID, null, this); 
} 

ऊपर आग और मेरे लोडर में मैं कर्सर, मज़बूती से है जो मिलता है संभाल करने के लिए बनाई गई है एक घुमाने के बाद पुराने डेटा है, लेकिन किसी भी अन्य परिस्थिति

@Override 
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) { 
    if(cursor.moveToFirst()){ 
     mYpos = cursor.getInt(cursor.getColumnIndex(ProductsContract.Products.Y_POS)); 
     Utils.logv("loader: " + mYpos); 
    } 
} 

तो restating में ठीक है, एक घुमाने के बाद, लोडर लगातार पुराने डेटा वितरित करेंगे।

मुझे लगता है कि शायद यह लोडर है जो स्टेल है और सामग्री प्रदाता स्वयं नहीं है? घुमावदार होने के बावजूद कर्सर को सहेजा और बहाल किया जाता है, भले ही यह बाँध हो?

+0

यह एंड्रॉइड 2.3 पर एसडीके 8 नमूना ऐप नोटपैड के साथ निश्चित रूप से मामला है। Resume() में एक ब्रेकपॉइंट सेट करें (लाइन पर या उससे पहले "mText.setTextKeepState (नोट);"), नोट में परिवर्तन करें, स्क्रीनलॉक सक्रिय करें, स्क्रीन अनलॉक करें, और नोट टेक्स्ट में अभी भी बदलाव होंगे जब स्क्रीनलॉक सक्रिय किया गया था। ऑनस्यूम() के माध्यम से कदम उठाएं और "स्ट्रिंग नोट = mCursor.getString (COLUMN_INDEX_NOTE) निष्पादित करने के बाद;" आपको मूल नोट टेक्स्ट बहाल करना चाहिए। – Huperniketes

उत्तर

1
It seems like an obvious race condition that the save to the content provider is not completed in the onPause before it is loaded after the rotate. 

बयान से ऊपर मानते हुए तक सही है:

आमतौर पर सामग्री प्रदाता तेज है और यह इतना समय लेने के लिए नहीं लगता है। लेकिन, ContetnProviderSQLite द्वारा समर्थित, यह समझ में आता है कि डेटाबेस में डेटा डालने में समय लगेगा। जहां देरी का समय डेटा और डिवाइस हार्डवेयर की मात्रा पर निर्भर करेगा।

लेकिन, इस दृष्टिकोण के साथ समस्या तब होती है जब उपयोगकर्ता स्क्रीन को घुमाता है और वास्तव में प्रतीक्षा करना पसंद नहीं करता है, यह देखने के लिए कि डेटा एक-एक करके लोड किया जा रहा है। इस मार्ग पर Rotation should be fast very fast.

वैकल्पिक, है

  • अपने कार्य को पूरा करने के लिए अपने प्रतीक्षा
  • आप प्रकट टैग सेट (इस यूआई को ब्लॉक करेगा अगली बार और बहुत बहुत बुरा विचार बनाया जा रहा है), जो घूर्णन का ख्याल रखना।

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

ContentProvider कुछ शानदार लाभ प्रदान करते हैं, इसमें कोई संदेह नहीं है। यदि आपको ContentProvider की आवश्यकता है तो आपको इसका उपयोग करना चाहिए। लेकिन, घूर्णन को संभालने के लिए आप अन्य विकल्प के बारे में सोच सकते हैं। और, समाधान के चारों तरफ एक फाइल पर चीजें डंपिंग होगी और उसे वापस पढ़ें। SharedPreferences या मेरे सिर के शीर्ष पर अभी सामान्य फ़ाइल IO। मुझे लगता है कि ये एक अच्छा कारण है कि ये मौजूद हैं।

आखिरकार, जिज्ञासा से बाहर, क्या आपने डेटा onResume खंड को लोड करके कोशिश की है? और, उम्मीद है कि setRetainInstance(boolean) आपके कोड में कहीं भी सेट नहीं है।

संपादित,

AFAIK, ContentProvider नहीं प्रदाता किसी भी atomicity या धागे सुरक्षा करते हैं। एंड्रॉयड दस्तावेज़ में

the methods query(), insert(), delete(), update(), and getType()—are called 
from a pool of threads in the content provider's process, not the UI thread 
for the process. Because these methods might be called from any number of 
threads at the same time, they too must be implemented to be thread-safe. 

पढ़ कृपया this और this

शायद मैं अगर मैं अपने कोड देख सकते हैं आप एक बेहतर जवाब देने के लिए सक्षम हो जाएगा।

+0

वैसे मैं अभी भी गीलेर के रूप में सोच रहा हूं या सामग्री प्रदाता परमाणु नहीं है। जो मुझे समझ में नहीं आता है वह है कि contentprovider कॉल afaik कॉल अवरुद्ध कर रहे हैं। और ऑन्रेस और ऑनक्रेट (जहां मैं लोड करता हूं) को ऑनपोज (जहां मैंने पढ़ा) के बाद बुलाया जाता है। यह समझने का एक लंबा सफर तय करेगा कि वास्तव में परमाणुता को तोड़ने वाला क्या है। मेरे पास एक काम है, और यह उस डेटा को saveoninstancestate का उपयोग करने के लिए है जिसे मुझे रोटेशन के माध्यम से संरक्षित करने की आवश्यकता है।यह सिर्फ एक और अधिक जटिल बना दिया गया है कि लोडर नई गतिविधि में कई बार वापस आ जाता है। यह कई बार वापस क्यों कॉल करता है, मैं भी नहीं जानता। –

+0

क्षमा करें, मिन्हज़, लेकिन आप समस्या का सारांश खो रहे हैं। व्यवहार जो ऑनपॉज() के एक आमंत्रण पर काम करता है, जब गतिविधि (या गतिविधि फ़्रेगमेंट) उदाहरण नष्ट हो रहा है क्योंकि उपयोगकर्ता बैक बटन हिट करता है, तब गतिविधि नहीं करता है जब गतिविधि (या गतिविधि फ़्रेगमेंट) नष्ट हो जाती है क्योंकि स्क्रीन को लॉक किया जाता है प्रणाली। ContentProvider का व्यवहार अलग है। हम इस कारण की तलाश में हैं कि क्यों, और यह अपेक्षा करने के लिए कैसे प्राप्त करें। – Huperniketes

+0

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

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