2012-08-17 19 views
18

http://developer.android.com/guide/components/loaders.html में पाया लोडर के लिए Android दस्तावेज़ में पर पुन: प्रारंभ होता यह कहते लोडर के गुणों में से एक है जो:लोडर उन्मुखीकरण परिवर्तन

जब एक विन्यास बदलने के बाद से निर्मित किया जा रहा वे स्वचालित रूप से पिछले लोडर के कर्सर से पुन: कनेक्ट। इस प्रकार, उन्हें अपने डेटा को फिर से पूछने की आवश्यकता नहीं है।

कोड है कि व्यवहार दर्पण प्रतीत नहीं होता है के बाद, एक नया लोडर एक खत्म ContentResolver क्वेरी करने बनाई गई है, तो मैं स्क्रीन बारी बारी से और लोडर फिर से बनाया जाता है!

08-17 16:49:54.474: D/TEST(1833): Creating loader 
08-17 16:49:55.074: D/TEST(1833): Load finished 
*Here I rotate the screen* 
08-17 16:50:38.115: D/TEST(1833): Creating loader 
08-17 16:50:38.353: D/TEST(1833): Load finished 

किसी भी विचार क्या मैं गलत कर रहा हूँ यहाँ:

public class ReportFragment extends Fragment implements LoaderCallbacks<Cursor> { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     getLoaderManager().initLoader(1, null, this); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 
     View v = inflater.inflate(R.layout.fragment_report, container, false); 
     return v; 
    } 

    public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) { 
     Log.d("TEST", "Creating loader"); 
     return new CursorLoader(getActivity(), ResourcesContract.Reports.CONTENT_URI, null, null, null, null); 
    } 

    public void onLoadFinished(Loader<Cursor> arg0, Cursor arg1) { 
     Log.d("TEST", "Load finished"); 
    } 

    public void onLoaderReset(Loader<Cursor> arg0) { 

    } 

} 

यहाँ मेरी logcat से उत्पादन होता है?

संपादित करें:

मैं नोट करना चाहिए कि मैं गूगल एपीआई संस्करण 8 Android में निर्माण कर रहा हूँ, और v4 समर्थन लाइब्रेरी का उपयोग कर।

2 संपादित करें:

यह समर्थन पुस्तकालय में एक बग के कारण सबसे अधिक संभावना है, इस बग प्रस्तुत करने पर एक नज़र डालें आप अधिक जानकारी चाहते हैं:

http://code.google.com/p/android/issues/detail?id=20791&can=5&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars

+1

अधिक जानकारी के लिए यह पोस्ट देखें: यदि आप 'getLoaderManager()' onActivityCreated' में बुलाना चाहिए 'इसके अलावा http://www.androiddesignpatterns.com/2012/08/implementing-loaders.html –

+2

, ... अपने वर्तमान कोड 'Fragment' पहली बार बनाई गई है, तो' गतिविधि' अभी भी शून्य 'है, तो' IllegalStateException' फेंक देगा। –

+1

@AlexLockwood, आपके उदाहरण में (अच्छी नौकरी!) आप समर्थन-v4: 18.0.0 का उपयोग कर रहे हैं। वर्तमान संस्करण 23.0.1 है और इसमें यह बग है। मैंने जो नवीनतम वर्किंग वर्जन परीक्षण किया है वह 22.0.0 है। –

उत्तर

-2

OnCreate () स्क्रीन अभिविन्यास परिवर्तन के दौरान बुलाया जाता है क्योंकि गतिविधि नष्ट हो जाती है और फिर से बनाई जाती है।

जब तक आप बहुत अधिक डेटा लोड नहीं कर रहे हैं तो यह करने में कोई दिक्कत नहीं होती है, लेकिन यदि आप चाहें तो आप निम्न कोशिश कर सकते हैं (मैंने इसका परीक्षण नहीं किया है, लेकिन सिद्धांत में मुझे लगता है कि यह काम करेगा)।

कक्षा के शीर्ष वैश्विक स्तर पर एक स्थिर बूलियन घोषित करें। मुझे लगता है कि आप भी संदर्भ के लिए

private static boolean dataDownloaded = false; 
private static Cursor oldCursor; 

तब पर बूलियन मान

@Override 
protected void onSaveInstanceState(Bundle outSave) { 
    outSave.putBoolen("datadownloaded", dataDownloaded); 
    oldCursor = adapter.swapCursor(null); 
} 

को बचाने के लिए सेट onLoadFinished dataDownloaded = सच

अवहेलना onSaveInstanceState एक स्थिर कर्सर की आवश्यकता होगी और onCreate जोड़ने

if (savedInstanceState != null) { 
    this.dataDownloaded = savedInstanceState.getBoolean("datadownloaded", false); 
} 

समायोजित अपने onCreateLoader

public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
    CursorLoader cursorLoader; 
    if (dataDownloaded) { 
     cursorLoader = new CursorLoader(getActivity(), 
      null, projection, null, null, null); 
     cursorLoader.deliverResult(oldCursor); 
    } else { 
     CursorLoader cursorLoader = new CursorLoader(getActivity(), 
      URI_PATH, projection, null, null, null); 
    } 

    return cursorLoader; 
} 
+0

यह सामग्री कंट्रोलरोलवर को किसी भी तरह से नहीं पूछता है (इससे कोई फर्क नहीं पड़ता कि डेटा डाउनलोड किया गया है या गलत है, एक नया कर्सर लोडर अभी भी बनाया गया है)? वैसे भी, मुझे लगता है कि यह वास्तव में समर्थन पुस्तकालयों के साथ एक बग के कारण हो रहा है, अधिक जानकारी के लिए इस पोस्ट को देखें: https://groups.google.com/forum/?fromgroups#!topic/android-developers/DbKL6PVyhLI%5B1- 25% 5 डी –

+0

मैंने इसे समायोजित किया .. यदि डेटा पहले से डाउनलोड किया गया था तो यूआरआई पथ के लिए "शून्य" होना चाहिए – ainesophaur

+0

अब समझ में आता है। खैर, यह एक समाधान है जहां तक ​​मैं देख सकता हूं इसलिए मैं इसे एक के रूप में चिह्नित करूंगा। आपके उत्तर के लिए धन्यवाद। –

-1

आप बस अगर लोडर पहले से ही मौजूद है onCreate देखने के लिए जाँच कर सकते हैं। फिर आप या तो init या पुनरारंभ कर सकते हैं।

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    if (getLoaderManager().getLoader(LOADER_ID) == null) { 
     getLoaderManager().initLoader(LOADER_ID, null, this); 
    } else { 
     getLoaderManager().restartLoader(LOADER_ID); 
    } 
} 

आप आमतौर पर अपने लोडर को एक आईडी पास करते हैं ताकि आप बाद में लोडर प्रबंधक के माध्यम से इसका संदर्भ दे सकें।

आशा है कि इससे मदद मिलती है!

+0

हाय नेल्सन, यह लोडर को पुनरारंभ करेगा यदि पहले से मौजूद है, तो किस तरह का उद्देश्य इसका उद्देश्य है।यहां तक ​​कि यदि आप दो कथन (इनिट और पुनरारंभ) को स्विच करना चाहते थे, तो इसके परिणामस्वरूप उसी व्यवहार में केवल इनिटलोडर को कॉल करना होगा! –

+2

getLoaderManager()। RestartLoader (LOADER_ID); पूरी तरह से "if() {} else {}" कथन के समान ही है क्योंकि लोडर अभी तक मौजूद नहीं है, तो पुनरारंभ लोडर ठीक वही करता है। –

0

अब तक मुझे पता चला है कि बनाए रखने वाले खंड Fragment.setRetainInstance(true) समर्थन पुस्तकालय का उपयोग करके अभिविन्यास परिवर्तन पर लोडर को पुनर्निर्मित करने से रोकता है। लोडर अंतिम परिणाम onLoadFinished() में अच्छी तरह से वितरित किए जाते हैं। यह कम से कम काम करता है जब गतिविधि एकल टुकड़े का प्रबंधन करती है और FragmentTransaction का उपयोग करके गतिविधि में खंड जोड़ा जाता है।

0

हालांकि यह एक छोटा सा सवाल है, मैं यहां अपने विचार रखना चाहता हूं।

onSaveInstanceState

में अतिरिक्त जानकारी के भंडारण के लिए जब एक विन्यास बदलने के बाद से निर्मित किया जा रहा ढांचे स्वचालित रूप से पिछले लोडर के कर्सर से पुन: कनेक्ट करने के लिए कोई जरूरत नहीं है। इस प्रकार, उन्हें अपने डेटा को फिर से पूछने की आवश्यकता नहीं है।

यह onCreate समारोह में मतलब है कि आप loaderManager कॉल करने के लिए केवल तभी savedInstanceState अशक्त

पूर्व है की जरूरत है: हालांकि यह कोई पुराना सवाल यह है कि

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    if(savedInstanceState == null) { 
     getLoaderManager().initLoader(1, null, this); 
    } 
} 
1

, मैं एक ही मुद्दे के रूप में अनुभव की जा रही ओपी लोडर का उपयोग करके, मुझे एक नई गतिविधि पर नेविगेट करते समय फिर से शुरू करना होगा, और फिर वापस। लेकिन साथ ही, मैं नहीं चाहता कि लोडर फिर से शुरू हो जाए जब मैं फोन की स्क्रीन घुमाता हूं।

मुझे जो मिला वह यह है कि अगर आप अपने सुपर को कॉल करने से पहले लोडर को पुनरारंभ करते हैं तो इसे रीस्टार्ट() में प्राप्त करना संभव है।

public class MainActivity extends AppCompatActivity implements 
LoaderManager.LoaderCallbacks<Cursor> { 

    ... 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     ... 

     //Initialize the loader. 
     getSupportLoaderManager().initLoader(0, null, this); 
    } 

    @Override 
    protected void onRestart() { 
     //Restart the loader before calling the super. 
     getSupportLoaderManager().restartLoader(LOADER_ID, null, this); 

     super.onRestart(); 
    } 

    ... 

} 
+0

+1 धन्यवाद :) इससे मुझे मेरी समस्या में मदद मिली :) मैं एडाप्टर व्यूफ्लिपर का उपयोग कर रहा हूं और अपने लोडर के प्रबंधन के लिए आपकी सलाह का पालन कर रहा हूं, फ्लिपर स्क्रीन रोटेशन से प्रभावित नहीं है :) –

0

मेरी राय में आप दस्तावेज़ीकरण के बारे में गलत समझते हैं। दस्तावेज कहता है, कि उन्हें अपने डेटा को दोबारा पूछने की आवश्यकता नहीं है, और ऐसा नहीं कर रहा है।

अपने ContentProvider#query() विधि में ब्रेकपॉइंट लॉग/डालने का प्रयास करें! क्वेरी केवल गतिविधि स्टार्टअप पर ही होगी, न कि अभिविन्यास परिवर्तन के बाद।

लेकिन यह LoaderCallbacks#onCreateLoader() विधि के लिए सत्य नहीं है। इसे प्रत्येक अभिविन्यास परिवर्तन के बाद बुलाया जाएगा, लेकिन इसका मतलब फिर से पूछताछ नहीं है, यह सिर्फ विधि को कॉल करता है ताकि आप चाहें तो कर्सर लोडर को बदल सकें।

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