अपने फ़्रैगमेंट डीबग करना

इस गाइड में ऐसे टूल के बारे में बताया गया है जिनका इस्तेमाल करके, अपनी फ़्रैगमेंट.

फ़्रैगमेंट मैनेजर में लॉग इन करना

FragmentManager इससे अलग-अलग तरह के मैसेज भेजे जा सकते हैं Logcat. यह सुविधा डिफ़ॉल्ट रूप से बंद होती है. लेकिन कभी-कभी इन लॉग मैसेज से आपको समस्या हल करने में मदद मिल सकती है. आपके फ़्रैगमेंट से जुड़ी समस्याएं हो सकती हैं. FragmentManager से सबसे काम का आउटपुट मिलता है DEBUG और VERBOSE के लॉग लेवल के हिसाब से.

आप इनका इस्तेमाल करके लॉग इन करने की सुविधा चालू कर सकते हैं adb shell निर्देश:

adb shell setprop log.tag.FragmentManager DEBUG

इसके अलावा, यहां दिए गए तरीके से वर्बोस लॉगिंग का इस्तेमाल किया जा सकता है:

adb shell setprop log.tag.FragmentManager VERBOSE

अगर आपने वर्बोस लॉगिंग को चालू किया है, तो लॉग लेवल फ़िल्टर को लॉगकैट विंडो में डालें. हालांकि, इस सिर्फ़ FragmentManager लॉग को ही नहीं, बल्कि सभी लॉग को फ़िल्टर करता है. आम तौर पर, यह करना सबसे अच्छा होता है अपनी ज़रूरत के हिसाब से लॉग लेवल पर, FragmentManager में लॉग इन करने की सुविधा चालू करें.

DEBUG लॉगिंग

DEBUG लेवल पर, FragmentManager आम तौर पर इससे जुड़े लॉग मैसेज दिखाता है लाइफ़साइकल की स्थिति में बदलाव होता है. हर लॉग एंट्री में toString() होता है Fragment से डंप करना है. लॉग एंट्री में नीचे दी गई जानकारी होती है:

  • Fragment इंस्टेंस का सिंपल क्लास नाम.
  • आइडेंटिटी हैश कोड Fragment इंस्टेंस में से.
  • Fragment इंस्टेंस के लिए फ़्रैगमेंट मैनेजर का यूनीक आईडी. यह स्थिर है कॉन्फ़िगरेशन में बदलाव करने के साथ-साथ, मौत और मनोरंजन की प्रोसेस को भी पूरा करता है.
  • उस कंटेनर का आईडी जिसमें Fragment को जोड़ा गया है. हालांकि, यह सिर्फ़ तब काम करेगा, जब जोड़ा गया हो.
  • Fragment टैग, अगर सेट हो.

यहां DEBUG लॉग की एंट्री का सैंपल दिया गया है:

D/FragmentManager: moveto ATTACHED: NavHostFragment{92d8f1d} (fd92599e-c349-4660-b2d6-0ece9ec72f7b id=0x7f080116)
  • Fragment क्लास NavHostFragment है.
  • पहचान हैश कोड 92d8f1d है.
  • यूनीक आईडी fd92599e-c349-4660-b2d6-0ece9ec72f7b है.
  • कंटेनर आईडी 0x7f080116 है.
  • टैग छोड़ दिया गया है क्योंकि कोई भी सेट नहीं था. मौजूद होने पर, यह इस तरह दिखता है tag=tag_value फ़ॉर्मैट में आईडी.

छोटे और पढ़ने में आसान होने के लिए, यूयूआईडी को यहां छोटा किया गया है उदाहरण.

यहां एक NavHostFragment शुरू किया जा रहा है और उसके बाद startDestination FirstFragment टाइप का Fragment बनाया जा रहा है और इसमें ट्रांज़िशन किया जा रहा है RESUMED स्थिति:

D/FragmentManager: moveto ATTACHED: NavHostFragment{92d8f1d} (<UUID> id=0x7f080116)
D/FragmentManager:   mName=null mIndex=-1 mCommitted=false
D/FragmentManager:   Operations:
D/FragmentManager:     Op #0: SET_PRIMARY_NAV NavHostFragment{92d8f1d} (<UUID> id=0x7f080116)
D/FragmentManager: moveto CREATED: NavHostFragment{92d8f1d} (<UUID> id=0x7f080116)
D/FragmentManager:   mName=null mIndex=-1 mCommitted=false
D/FragmentManager:   Operations:
D/FragmentManager:     Op #0: REPLACE FirstFragment{ccd2189} (<UUID> id=0x7f080116)
D/FragmentManager:     Op #1: SET_PRIMARY_NAV FirstFragment{ccd2189} (<UUID> id=0x7f080116)
D/FragmentManager: moveto ATTACHED: FirstFragment{ccd2189} (<UUID> id=0x7f080116)
D/FragmentManager: moveto CREATED: FirstFragment{ccd2189} (<UUID> id=0x7f080116)
D/FragmentManager: moveto CREATE_VIEW: NavHostFragment{92d8f1d} (<UUID> id=0x7f080116)
D/FragmentManager: moveto CREATE_VIEW: FirstFragment{ccd2189} (<UUID> id=0x7f080116)
D/FragmentManager: moveto ACTIVITY_CREATED: NavHostFragment{92d8f1d} (<UUID> id=0x7f080116)
D/FragmentManager: moveto RESTORE_VIEW_STATE: NavHostFragment{92d8f1d} (<UUID> id=0x7f080116)
D/FragmentManager: moveto ACTIVITY_CREATED: FirstFragment{ccd2189} (<UUID> id=0x7f080116)
D/FragmentManager: moveto RESTORE_VIEW_STATE: FirstFragment{ccd2189} (<UUID> id=0x7f080116)
D/FragmentManager: moveto STARTED: NavHostFragment{92d8f1d} (<UUID> id=0x7f080116)
D/FragmentManager: moveto STARTED: FirstFragment{ccd2189} (<UUID> id=0x7f080116)
D/FragmentManager: moveto RESUMED: NavHostFragment{92d8f1d} (<UUID> id=0x7f080116)
D/FragmentManager: moveto RESUMED: FirstFragment{ccd2189} (<UUID> id=0x7f080116)

उपयोगकर्ता इंटरैक्शन के बाद, FirstFragment अलग-अलग लाइफ़साइकल स्टेट के लिए किया जा सकता है. फिर SecondFragment इंस्टैंशिएट होता है और ट्रांज़िशन होता है से RESUMED स्थिति तक:

D/FragmentManager:   mName=07c8a5e8-54a3-4e21-b2cc-c8efc37c4cf5 mIndex=-1 mCommitted=false
D/FragmentManager:   Operations:
D/FragmentManager:     Op #0: REPLACE SecondFragment{84132db} (<UUID> id=0x7f080116)
D/FragmentManager:     Op #1: SET_PRIMARY_NAV SecondFragment{84132db} (<UUID> id=0x7f080116)
D/FragmentManager: movefrom RESUMED: FirstFragment{ccd2189} (<UUID> id=0x7f080116)
D/FragmentManager: movefrom STARTED: FirstFragment{ccd2189} (<UUID> id=0x7f080116)
D/FragmentManager: movefrom ACTIVITY_CREATED: FirstFragment{ccd2189} (<UUID> id=0x7f080116)
D/FragmentManager: moveto ATTACHED: SecondFragment{84132db} (<UUID> id=0x7f080116)
D/FragmentManager: moveto CREATED: SecondFragment{84132db} (<UUID> id=0x7f080116)
D/FragmentManager: moveto CREATE_VIEW: SecondFragment{84132db} (<UUID> id=0x7f080116)
D/FragmentManager: moveto ACTIVITY_CREATED: SecondFragment{84132db} (<UUID> id=0x7f080116)
D/FragmentManager: moveto RESTORE_VIEW_STATE: SecondFragment{84132db} (<UUID> id=0x7f080116)
D/FragmentManager: moveto STARTED: SecondFragment{84132db} (<UUID> id=0x7f080116)
D/FragmentManager: movefrom CREATE_VIEW: FirstFragment{ccd2189} (<UUID> id=0x7f080116)
D/FragmentManager: moveto RESUMED: SecondFragment{84132db} (<UUID> id=0x7f080116)

सभी Fragment इंस्टेंस को किसी आइडेंटिफ़ायर से सफ़िक्स के तौर पर जोड़ा गया है, ताकि आप इन्हें ट्रैक कर सकें की अलग-अलग घटनाएं एक जैसी Fragment क्लास.

VERBOSE लॉगिंग

VERBOSE लेवल पर, FragmentManager आम तौर पर इसके बारे में लॉग मैसेज देता है आंतरिक स्थिति:

V/FragmentManager: Run: BackStackEntry{f9d3ff3}
V/FragmentManager: add: NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: Added fragment to active set NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 1 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)
D/FragmentManager: moveto ATTACHED: NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: Commit: BackStackEntry{5cfd2ae}
D/FragmentManager:   mName=null mIndex=-1 mCommitted=false
D/FragmentManager:   Operations:
D/FragmentManager:     Op #0: SET_PRIMARY_NAV NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 1 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)
D/FragmentManager: moveto CREATED: NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: Commit: BackStackEntry{e93833f}
D/FragmentManager:   mName=null mIndex=-1 mCommitted=false
D/FragmentManager:   Operations:
D/FragmentManager:     Op #0: REPLACE FirstFragment{886440c} (<UUID> id=0x7f080130)
D/FragmentManager:     Op #1: SET_PRIMARY_NAV FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: Run: BackStackEntry{e93833f}
V/FragmentManager: add: FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: Added fragment to active set FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 1 for FirstFragment{886440c} (<UUID> id=0x7f080130)
D/FragmentManager: moveto ATTACHED: FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 1 for FirstFragment{886440c} (<UUID> id=0x7f080130)
D/FragmentManager: moveto CREATED: FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 1 for FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 1 for FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 1 for FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 1 for FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 1 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 1 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 1 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 4 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)
D/FragmentManager: moveto CREATE_VIEW: NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 2 for FirstFragment{886440c} (<UUID> id=0x7f080130)
D/FragmentManager: moveto CREATE_VIEW: FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 2 for FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 2 for FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 4 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)
D/FragmentManager: moveto ACTIVITY_CREATED: NavHostFragment{86274b0} (<UUID> id=0x7f080130)
D/FragmentManager: moveto RESTORE_VIEW_STATE: NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 4 for FirstFragment{886440c} (<UUID> id=0x7f080130)
D/FragmentManager: moveto ACTIVITY_CREATED: FirstFragment{886440c} (<UUID> id=0x7f080130)
D/FragmentManager: moveto RESTORE_VIEW_STATE: FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 4 for FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: SpecialEffectsController: Enqueuing add operation for fragment FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 4 for FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 4 for FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: SpecialEffectsController: For fragment FirstFragment{886440c} (<UUID> id=0x7f080130) mFinalState = VISIBLE -> VISIBLE.
V/FragmentManager: SpecialEffectsController: Container androidx.fragment.app.FragmentContainerView{7578ffa V.E...... ......I. 0,0-0,0 #7f080130 app:id/nav_host_fragment_content_fragment} is not attached to window. Cancelling pending operation Operation {382a9ab} {mFinalState = VISIBLE} {mLifecycleImpact = ADDING} {mFragment = FirstFragment{886440c} (<UUID> id=0x7f080130)}
V/FragmentManager: SpecialEffectsController: Operation {382a9ab} {mFinalState = VISIBLE} {mLifecycleImpact = ADDING} {mFragment = FirstFragment{886440c} (<UUID> id=0x7f080130)} has called complete.
V/FragmentManager: SpecialEffectsController: Setting view androidx.constraintlayout.widget.ConstraintLayout{3968808 I.E...... ......I. 0,0-0,0} to VISIBLE
V/FragmentManager: computeExpectedState() of 4 for FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 4 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: SpecialEffectsController: Enqueuing add operation for fragment NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 4 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 4 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: SpecialEffectsController: For fragment NavHostFragment{86274b0} (<UUID> id=0x7f080130) mFinalState = VISIBLE -> VISIBLE.
V/FragmentManager: SpecialEffectsController: Container androidx.fragment.app.FragmentContainerView{2ba8ba1 V.E...... ......I. 0,0-0,0 #7f080130 app:id/nav_host_fragment_content_fragment} is not attached to window. Cancelling pending operation Operation {f7eb1c6} {mFinalState = VISIBLE} {mLifecycleImpact = ADDING} {mFragment = NavHostFragment{86274b0} (<UUID> id=0x7f080130)}
V/FragmentManager: SpecialEffectsController: Operation {f7eb1c6} {mFinalState = VISIBLE} {mLifecycleImpact = ADDING} {mFragment = NavHostFragment{86274b0} (<UUID> id=0x7f080130)} has called complete.
V/FragmentManager: SpecialEffectsController: Setting view androidx.fragment.app.FragmentContainerView{7578ffa I.E...... ......I. 0,0-0,0 #7f080130 app:id/nav_host_fragment_content_fragment} to VISIBLE
V/FragmentManager: computeExpectedState() of 4 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: Run: BackStackEntry{5cfd2ae}
V/FragmentManager: computeExpectedState() of 4 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 4 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 4 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 5 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)
D/FragmentManager: moveto STARTED: NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 5 for FirstFragment{886440c} (<UUID> id=0x7f080130)
D/FragmentManager: moveto STARTED: FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 5 for FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 5 for FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 5 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 5 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 7 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 7 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)
D/FragmentManager: moveto RESUMED: NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 7 for FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 7 for FirstFragment{886440c} (<UUID> id=0x7f080130)
D/FragmentManager: moveto RESUMED: FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 7 for FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 7 for FirstFragment{886440c} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 7 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)
V/FragmentManager: computeExpectedState() of 7 for NavHostFragment{86274b0} (<UUID> id=0x7f080130)

इस उदाहरण में, सिर्फ़ FirstFragment पर लोड होने वाली जानकारी शामिल है. इसमें ट्रांज़िशन शामिल है SecondFragment लॉग एंट्री को काफ़ी बढ़ाता है. VERBOSE लेवल के कई लॉग मैसेज, ऐप्लिकेशन के लिए बहुत कम काम के होते हैं डेवलपर. हालांकि, पिछली गतिविधियों में बदलाव होने पर, आपको कुछ समस्याओं को डीबग किया जा रहा है.

फ़्रैगमेंट के लिए StrictMode

वर्शन 1.4.0 और Jetpack फ़्रैगमेंट लाइब्रेरी में ये शामिल हैं फ़्रैगमेंट के लिए StrictMode. यह कुछ ऐसी सामान्य समस्याओं को रोक सकता है जिनसे आपकी ऐप्लिकेशन का गलत इस्तेमाल न किया जा सके. इनके साथ काम करने से जुड़ी ज़्यादा जानकारी पाने के लिए, StrictMode, StrictMode पर जाकर इसे देखें.

कस्टम Policy इससे पता चलता है कि किस तरह के उल्लंघनों का पता चलता है. साथ ही, यह भी पता चलता है कि किस तरह के जुर्माने का पता लगाया जाता है नीतियों के उल्लंघन का पता चलता है.

कोई कस्टम StrictMode नीति लागू करने के लिए, इसे FragmentManager. इसे जल्द से जल्द करें. इस मामले में, आपको किसी init ब्लॉक या Java कंस्ट्रक्टर में:

Kotlin

class ExampleActivity : AppCompatActivity() {

    init {
        supportFragmentManager.strictModePolicy =
            FragmentStrictMode.Policy.Builder()
                .penaltyDeath()
                .detectFragmentReuse()
                .allowViolation(FirstFragment::class.java,
                                FragmentReuseViolation::class.java)
                .build()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val binding = ActivityExampleBinding.inflate(layoutInflater)
        setContentView(binding.root)
        ...
   }
}

Java

class ExampleActivity extends AppCompatActivity() {

    ExampleActivity() {
        getSupportFragmentManager().setStrictModePolicy(
                new FragmentStrictMode.Policy.Builder()
                        .penaltyDeath()
                        .detectFragmentReuse()
                        .allowViolation(FirstFragment.class,
                                        FragmentReuseViolation.class)
                        .build()
        );
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState)

        ActivityExampleBinding binding =
            ActivityExampleBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        ...
   }
}

ऐसे मामलों में जहां आपको Context को जानने की ज़रूरत है, ताकि यह तय किया जा सके कि StrictMode को चालू करने पर, जैसे कि किसी बूलियन रिसॉर्स की वैल्यू से, आप नीचे दिए गए काम कर सकते हैं FragmentManager को StrictMode नीति असाइन करने से रोकने के लिए OnContextAvailableListener:

Kotlin

class ExampleActivity : AppCompatActivity() {

    init {
        addOnContextAvailableListener { context ->
            if(context.resources.getBoolean(R.bool.enable_strict_mode)) {
                supportFragmentManager.strictModePolicy = FragmentStrictMode.Policy.Builder()
                    .penaltyDeath()
                    .detectFragmentReuse()
                    .allowViolation(FirstFragment::class.java, FragmentReuseViolation::class.java)
                    .build()
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val binding = ActivityExampleBinding.inflate(layoutInflater)
        setContentView(binding.root)
        ...
   }
}

Java

class ExampleActivity extends AppCompatActivity() {

    ExampleActivity() {
        addOnContextAvailableListener((context) -> {
            if(context.getResources().getBoolean(R.bool.enable_strict_mode)) {
                getSupportFragmentManager().setStrictModePolicy(
                        new FragmentStrictMode.Policy.Builder()
                                .penaltyDeath()
                                .detectFragmentReuse()
                                .allowViolation(FirstFragment.class, FragmentReuseViolation.class)
                                .build()
                );
            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState)

        ActivityExampleBinding binding = ActivityExampleBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        ...
   }
}

नया पॉइंट जहां से StrictMode को कॉन्फ़िगर किया जा सकता है, ताकि हर संभव तरीके से गड़बड़ियों का पता चल सके उल्लंघन onCreate() super.onCreate() पर कॉल करने से पहले:

Kotlin

class ExampleActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        supportFragmentManager.strictModePolicy = FragmentStrictMode.Policy.Builder()
            .penaltyDeath()
            .detectFragmentReuse()
            .allowViolation(FirstFragment::class.java, FragmentReuseViolation::class.java)
            .build()

        super.onCreate(savedInstanceState)

        val binding = ActivityExampleBinding.inflate(layoutInflater)
        setContentView(binding.root)
        ...
   }
}

Java

class ExampleActivity extends AppCompatActivity() {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        getSupportFragmentManager().setStrictModePolicy(
                new FragmentStrictMode.Policy.Builder()
                        .penaltyDeath()
                        .detectFragmentReuse()
                        .allowViolation(FirstFragment.class, FragmentReuseViolation.class)
                        .build()
                );

        super.onCreate(savedInstanceState)

        ActivityExampleBinding binding = ActivityExampleBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        ...
   }
}

इन उदाहरणों में इस्तेमाल की गई नीति, सिर्फ़ फ़्रैगमेंट के फिर से इस्तेमाल से जुड़े उल्लंघनों का पता लगाती है, और ऐसा होने पर ऐप्लिकेशन बंद हो जाता है. penaltyDeath() यह डीबग करने में मददगार होता है, क्योंकि यह इतनी तेज़ी से फ़ेल हो जाता है कि आप इसे अनदेखा नहीं कर सकते उल्लंघन.

कुछ उल्लंघनों की अनुमति चुनिंदा तरीके से दी जा सकती है. इसमें इस्तेमाल की गई नीति हालांकि, ऊपर दिए गए उदाहरण में, बाकी सभी फ़्रैगमेंट के लिए इस उल्लंघन को लागू किया जाता है प्रकार. यह उन मामलों में फ़ायदेमंद होता है जहां तीसरे पक्ष का लाइब्रेरी कॉम्पोनेंट StrictMode के उल्लंघन शामिल होने चाहिए.

ऐसे मामलों में, उन उल्लंघन को कुछ समय के लिए, अनुमति वाली सूची में जोड़ा जा सकता है लाइब्रेरी से पहले तक आपके पास मौजूद कॉम्पोनेंट के लिए, StrictMode के बारे में जानकारी उनका उल्लंघन ठीक करती है.

अन्य उल्लंघनों को कॉन्फ़िगर करने के तरीके की जानकारी के लिए, FragmentStrictMode.Policy.Builder.

पेनल्टी तीन तरह की होती है.

  • penaltyLog() नीतियों के उल्लंघन की जानकारी Logcat में डाल देता है.
  • penaltyDeath() नीति के उल्लंघन का पता चलने पर, ऐप्लिकेशन को बंद कर दिया जाता है.
  • penaltyListener() कस्टम लिसनर जोड़ने की सुविधा देता है, जिसे नीतियों का उल्लंघन होने पर की पहचान की गई.

अपने Policy में, किसी भी तरह के जुर्माने लागू किए जा सकते हैं. अगर आपकी नीति साफ़ तौर पर जुर्माने की जानकारी नहीं देता है, तो डिफ़ॉल्ट रूप से penaltyLog() का इस्तेमाल किया गया है. अगर आपको अपनी पसंद के मुताबिक बनाए गए Policy में, penaltyLog() के अलावा कोई दूसरा जुर्माना लगाएं. इसके बाद penaltyLog() बंद रहेगा, जब तक कि इसे साफ़ तौर पर सेट नहीं किया जाता.

penaltyListener() तब काम आ सकता है, जब आपके पास तीसरे पक्ष की लॉगिंग लाइब्रेरी हो जिसके उल्लंघन की जानकारी को लॉग करना है. इसके अलावा, आपके पास अपनी पसंद के मुताबिक रिलीज़ बिल्ड में मौजूद नुकसान न पहुंचाने वाले उल्लंघन का पता लगाना और उन्हें क्रैश रिपोर्टिंग में लॉग करना लाइब्रेरी. इस रणनीति से ऐसे उल्लंघनों का पता लगाया जा सकता है जो छूट गए थे.

वैश्विक StrictMode नीति सेट करने के लिए, ऐसी डिफ़ॉल्ट नीति सेट करें जो सभी पर लागू होती हो FragmentManager इंस्टेंस FragmentStrictMode.setDefaultPolicy() तरीका:

Kotlin

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        FragmentStrictMode.defaultPolicy =
            FragmentStrictMode.Policy.Builder()
                .detectFragmentReuse()
                .detectFragmentTagUsage()
                .detectRetainInstanceUsage()
                .detectSetUserVisibleHint()
                .detectTargetFragmentUsage()
                .detectWrongFragmentContainer()
                .apply {
                    if (BuildConfig.DEBUG) {
                        // Fail early on DEBUG builds
                        penaltyDeath()
                    } else {
                        // Log to Crashlytics on RELEASE builds
                        penaltyListener {
                            FirebaseCrashlytics.getInstance().recordException(it)
                        }
                    }
                }
                .build()
    }
}

Java

public class MyApplication extends Application {

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

        FragmentStrictMode.Policy.Builder builder = new FragmentStrictMode.Policy.Builder();
        builder.detectFragmentReuse()
                .detectFragmentTagUsage()
                .detectRetainInstanceUsage()
                .detectSetUserVisibleHint()
                .detectTargetFragmentUsage()
                .detectWrongFragmentContainer();
        if (BuildConfig.DEBUG) {
            // Fail early on DEBUG builds
            builder.penaltyDeath();
        } else {
            // Log to Crashlytics on RELEASE builds
            builder.penaltyListener((exception) ->
                    FirebaseCrashlytics.getInstance().recordException(exception)
            );
        }
        FragmentStrictMode.setDefaultPolicy(builder.build());
    }
}

यहां दिए सेक्शन में, अलग-अलग तरह के उल्लंघनों और उनके समाधान के बारे में बताया गया है.

फ़्रैगमेंट का फिर से इस्तेमाल

फ़्रैगमेंट के फिर से इस्तेमाल से जुड़े उल्लंघन को इसका इस्तेमाल करके चालू किया गया है detectFragmentReuse() और फेंकता है FragmentReuseViolation.

इस उल्लंघन का मतलब है कि Fragment इंस्टेंस हटाने के बाद, उसका फिर से इस्तेमाल किया गया है FragmentManager से. दोबारा इस्तेमाल करने से समस्याएं हो सकती हैं, क्योंकि Fragment इससे पिछले इस्तेमाल की स्थिति बरकरार रहती है और लगातार काम नहीं करती. अगर आपको नया इंस्टेंस हर बार, जब उसे जोड़ा जाता है, तो यह हमेशा शुरुआती स्थिति में होता है FragmentManager.

फ़्रैगमेंट टैग का इस्तेमाल

फ़्रैगमेंट टैग के इस्तेमाल से जुड़े उल्लंघन को इसका इस्तेमाल करके चालू किया गया है detectFragmentTagUsage() और फेंकता है FragmentTagUsageViolation.

इस उल्लंघन से पता चलता है कि Fragment को <fragment> का इस्तेमाल करके बढ़ाया गया है एक एक्सएमएल लेआउट में इसे ठीक करने के लिए, Fragment को अंदर की ओर बढ़ाएं <fragment> के बजाय <androidx.fragment.app.FragmentContainerView> टैग के साथ जोड़ा जा सकता है. FragmentContainerView का इस्तेमाल करके बढ़ाए गए फ़्रैगमेंट भरोसेमंद तरीके से हैंडल कर सकते हैं Fragment के लेन-देन और कॉन्फ़िगरेशन में बदलाव. ये शायद इस तरह काम न करें अगर आप इसके बजाय <fragment> टैग का इस्तेमाल करते हैं, तो यह उम्मीद की जाती है.

इंस्टेंस का इस्तेमाल बनाए रखें

इसका इस्तेमाल करके बनाए रखने के इंस्टेंस के इस्तेमाल से जुड़े उल्लंघन को चालू किया गया है detectRetainInstanceUsage() और फेंकता है RetainInstanceUsageViolation.

यह उल्लंघन, रिटेन किए गए Fragment के इस्तेमाल को दिखाता है. खास तौर पर, अगर आपके पास कॉल करने की सुविधा है setRetainInstance() या getRetainInstance(), ये दोनों अब काम नहीं करते.

बनाए रखे गए Fragment इंस्टेंस को मैनेज करने के लिए, इन तरीकों का इस्तेमाल करने के बजाय स्टोर करने के लिए ViewModel जो आपके लिए यह काम करती है.

उपयोगकर्ता को दिखने वाला संकेत सेट करें

सेट उपयोगकर्ता को दिखने वाले संकेत के उल्लंघन को इसका इस्तेमाल करके चालू किया गया है detectSetUserVisibleHint() और फेंकता है SetUserVisibleHintViolation.

इस उल्लंघन का मतलब है कि setUserVisibleHint() यह सुविधा अब काम नहीं करती.

अगर इस तरीके को मैन्युअल तरीके से कॉल किया जा रहा है, तो setMaxLifecycle() आज़माएं. अगर इस तरीके को बदला जाता है, तो व्यवहार को onResume() true में गुजरने पर और onPause() जब false में पास हो रहा हो.

टारगेट फ़्रैगमेंट का इस्तेमाल

इसका इस्तेमाल करके टारगेट फ़्रैगमेंट के इस्तेमाल से जुड़े उल्लंघन को चालू किया गया है detectTargetFragmentUsage() और फेंकता है TargetFragmentUsageViolation.

इस उल्लंघन का मतलब है कि setTargetFragment() getTargetFragment(), या getTargetRequestCode(), जो सभी सुविधाएं अब काम नहीं करतीं. इन तरीकों का इस्तेमाल करने के बजाय, FragmentResultListener. पास होने के नतीजों के बारे में ज़्यादा जानकारी के लिए, इसके बीच के नतीजे पास करें फ़्रैगमेंट.

गलत फ़्रैगमेंट कंटेनर

इसका इस्तेमाल करके गलत फ़्रैगमेंट कंटेनर उल्लंघन को चालू किया गया है detectWrongFragmentContainer() और फेंकता है WrongFragmentContainerViolation.

इस उल्लंघन का मतलब है कि Fragment को इसके अलावा किसी दूसरे कंटेनर में जोड़ा गया है FragmentContainerView. Fragment टैग के इस्तेमाल की तरह, फ़्रैगमेंट ट्रांज़ैक्शन तब तक उम्मीद के मुताबिक काम नहीं करेंगे, जब तक कि FragmentContainerView. कंटेनर व्यू का इस्तेमाल करने से, View एपीआई में मौजूद उस समस्या को हल करने में भी मदद मिलती है जो इससे एग्ज़िट ऐनिमेशन का इस्तेमाल करने वाले फ़्रैगमेंट, बाकी सभी के ऊपर बनाए जाते हैं फ़्रैगमेंट.