मैं टुकड़ों में गैर-डिफ़ॉल्ट निर्माणकर्ताओं से क्यों बचना चाहता हूं?


173

मैं एक ऐप बना रहा हूं Fragmentsऔर उनमें से एक में मैंने एक नॉन-डिफॉल्ट कंस्ट्रक्टर बनाया और यह चेतावनी मिली:

Avoid non-default constructors in fragments: use a default constructor plus Fragment#setArguments(Bundle) instead

क्या कोई मुझे बता सकता है कि यह एक अच्छा विचार क्यों नहीं है?

क्या आप यह भी सुझाव दे सकते हैं कि मैं इसे कैसे पूरा करूंगा:

public static class MenuFragment extends ListFragment {
    public ListView listView1;
    Categories category;

    //this is my "non-default" constructor
    public MenuFragment(Categories category){
        this.category = category;
    }....

बिना डिफॉल्ट कंस्ट्रक्टर का उपयोग किए बिना?



3
नहीं, वे मदद नहीं करते। उन्होंने मेरे सवाल का जवाब नहीं दिया। लेकिन धन्यवाद कोई भी कम नहीं :)
BlackHatSamurai

31
@BlaineOmega वास्तव में यह विशेष रूप से एक है: stackoverflow.com/a/11602478/321697 निश्चित रूप से आपके प्रश्न का उत्तर देता है। एक अभिविन्यास परिवर्तन या अन्य घटना के कारण जो फ्रैगमेंट को फिर से बनाने का कारण बनता है, एंड्रॉइड डिफ़ॉल्ट निर्माणकर्ता के साथ-साथ बंडल को एक तर्क के रूप में पारित करता है। यदि आप एक कस्टम कंस्ट्रक्टर का उपयोग कर रहे हैं, तो जैसे ही इन घटनाओं में से एक के कारण टुकड़े को फिर से बनाया गया है, आपने कस्टम कंस्ट्रक्टर में जो कुछ भी किया था वह खो गया है।
केविन कोप्पॉक

1
धन्यवाद, लेकिन यह उत्तर क्यों, लेकिन कैसे नहीं।
ब्लैकहैटसमुरी

यह मेरी मूल टिप्पणी में पहले और दूसरे लिंक द्वारा कवर किया गया है।
कॉमन्सवेयर

जवाबों:


110

एक बंडल ऑब्जेक्ट बनाएं और अपना डेटा डालें (इस उदाहरण में आपकी Categoryऑब्जेक्ट)। सावधान रहें, आप इस वस्तु को सीधे बंडल में पारित नहीं कर सकते, जब तक कि यह धारावाहिक न हो। मुझे लगता है कि टुकड़े में अपनी वस्तु का निर्माण करना बेहतर है, और केवल एक आईडी या कुछ और बंडल में डालें। यह बंडल बनाने और संलग्न करने का कोड है:

Bundle args = new Bundle();
args.putLong("key", value);
yourFragment.setArguments(args);

उसके बाद, आपके खंड एक्सेस डेटा में:

Type value = getArguments().getType("key");

बस इतना ही।


3
कैसे एक वस्तु पारित करने के लिए? मैं एक संदर्भ वस्तु या किसी अन्य वस्तु को पारित करना चाहता हूं।
आदिल मलिक

12
बंडलों क्रमबद्ध जावा वस्तुओं के साथ-साथ Parcelableवस्तुओं को ले जा सकता है । इसके अलावा, आपको एक पास नहीं करना चाहिए Context, क्योंकि उस जानकारी को टुकड़े की getActivity()विधि के माध्यम से पहुँचा जा सकता है ।
कृतकौता

टुकड़े टुकड़े में यह कहाँ करना है Type value = getArguments().getType("key");?
मुहम्मद बाबर

4
@ मुहम्मद बाबर: अगर मैं आप होते, तो मैं इसे newInstance()विधि में शामिल करता। उदाहरण के लिए public static FragmentName newInstance(your variables){}:। जैसा कि एंड्रॉइड डॉक्यूमेंटेशन अनुशंसा करता है, मापदंडों के साथ एक कंस्ट्रक्टर न बनाएं, क्योंकि आपके टुकड़े के पुनरारंभ होने के बाद डिफ़ॉल्ट एक (बिना मापदंडों) स्वचालित रूप से कॉल किया जाएगा।
nistv4n


272

ऐसा लगता है कि जवाबों में से कोई भी वास्तव में जवाब नहीं देता है "नॉन डिफॉल्ट कंस्ट्रक्टरों के बजाय गुजर मापदंडों के लिए बंडल का उपयोग क्यों करें"

बंडल के माध्यम से आपको पैरामीटर क्यों पारित करना चाहिए, इसका कारण यह है कि जब सिस्टम एक पुनर्स्थापित करता है fragment(जैसे कॉन्फ़िगरेशन परिवर्तन पर), तो यह स्वचालित रूप से आपके को पुनर्स्थापित करेगा bundle

कॉलबैक जैसे मापदंडों को पढ़ना चाहिए onCreateया onCreateViewकरना चाहिए bundle- इस तरह से आपको fragmentउसी राज्य की सही स्थिति को बहाल करने की गारंटी दी fragmentगई है जिसके साथ आरंभिक था (ध्यान दें कि यह राज्य onSaveInstanceState bundleउस से अलग हो सकता है onCreate/onCreateView)

स्थैतिक newInstance()विधि का उपयोग करने की सिफारिश सिर्फ एक सिफारिश है। आप एक नॉन डिफॉल्ट कंस्ट्रक्टर का उपयोग कर सकते हैं, लेकिन सुनिश्चित करें कि आप bundleउस कंस्ट्रक्टर के शरीर के अंदर के इनिशियलाइज़ेशन पैरामीटर को पॉप्युलेट करते हैं । और उन मापदंडों को onCreate()या onCreateView()विधियों में पढ़ें ।


2
अच्छी तरह समझाया। धन्यवाद। अगर मैं एक सवाल पूछा जाता, तो मैं आपको एक टिक देता
Karue Benson Karue

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

51

आपके Fragmentपास निर्माणकर्ता नहीं होने चाहिए क्योंकि FragmentManagerयह कैसे तात्कालिक बनाता है। आपके पास newInstance()आवश्यक मानकों के साथ परिभाषित एक स्थिर विधि होनी चाहिए , फिर उन्हें बंडल करें और उन्हें टुकड़े के तर्क के रूप में सेट करें, जिसे आप बाद में Bundleपैरामीटर के साथ उपयोग कर सकते हैं ।

उदाहरण के लिए:

public static MyFragment newInstance(int title, String message) {
    MyFragment fragment = new MyFragment();
    Bundle bundle = new Bundle(2);
    bundle.putInt(EXTRA_TITLE, title);
    bundle.putString(EXTRA_MESSAGE, message);
    fragment.setArguments(bundle);
    return fragment ;
}

और इन तर्कों को पढ़ें onCreate:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    title = getArguments().getInt(EXTRA_TITLE);
    message = getArguments().getString(EXTRA_MESSAGE);

    //...
}

इस तरह, यदि अलग और फिर से संलग्न, वस्तु स्थिति को तर्कों के माध्यम से संग्रहीत किया जा सकता है, बहुत कुछ एस से bundlesजुड़ा हुआ है Intent


9

यदि आप कुछ कक्षा के लिए पैरामीटर का उपयोग करते हैं। इसे इस्तेमाल करे

SomeClass mSomeInstance;
public static final MyFragment newInstance(SomeClass someInstance){
    MyFragment f = new MyFragment();
    f.mSomeInstance = someInstance;
    return f;
}

5
यह वास्तव में एक बुरा सुझाव है। एक बार जब फ्रैगमेंट फिर से बनाया FragmentManagerजाएगा, तो आप mSomeInstance खो देंगे।
यारोस्लाव मायटक्लाइक

सहमत, SomeClass parcelable होना चाहिए और setArguments () का उपयोग करके एक बंडल में संग्रहीत किया जाना चाहिए
Jake_

1

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

अपनी परियोजनाओं में, मैं कोटलिन का उपयोग करता हूं, और तर्कों के लिए एक प्राथमिक नो-आर्ग कंस्ट्रक्टर और द्वितीयक कंस्ट्रक्टर के साथ टुकड़ों को लागू करता हूं जो उन्हें केवल एक बंडल में संग्रहीत करता है और इसे फ्रैगमेंट तर्कों के रूप में सेट करता है, सब कुछ ठीक काम करता है।


0

यदि फ़्रेग्मेंटेशन बदलने के बाद फ़्रेग्मेंट नॉन-डिफॉल्ट कंस्ट्रक्टर का उपयोग करता है, तो सभी डेटा खो जाएगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.