NullPointerException जब कोटलिन टुकड़े में विचारों को एक्सेस करने की कोशिश कर रहा हो


240

कोटलिन Android एक्सटेंशन का उपयोग कैसे करें Fragment? अगर मैं उनका उपयोग अंदर करता onCreateView()हूं, तो मुझे यह NullPointerExceptionअपवाद मिलता है:

इसके कारण: java.lang.NullPointerException: आभासी पद्धति 'android.view.View android.view.View.find.findViewById (int)' को एक अशक्त ऑब्जेक्ट संदर्भ पर लागू करने का प्रयास करें

यहाँ खंड कोड है:

package com.obaied.testrun.Fragment

import android.os.Bundle
import android.support.v4.app.Fragment
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.obaied.acaan.R
import kotlinx.android.synthetic.main.fragment_card_selector.*

public class CardSelectorFragment : Fragment() {
    val TAG = javaClass.canonicalName

    companion object {
        fun newInstance(): CardSelectorFragment {
            return CardSelectorFragment()
        }
    }

    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        var rootView = inflater?.inflate(R.layout.fragment_card_selector, container, false)
        btn_K.setOnClickListener { Log.d(TAG, "onViewCreated(): hello world"); }

        return rootView
    }
}
`

4
यदि आप इसे onCreateView में करना चाहते हैं, तो btn_K rootView पर भी एक संपत्ति होगी। आप कर सकते हैंrootView.btn_K.setOnClickListener
Makotosan

धन्यवाद @Makotosan आपके जवाब ने मेरे लिए काम किया।
महदी बागजानी

Android स्टूडियो ने मेरे लिए काम किया, स्वच्छ, पुनर्निर्माण और पुनः आरंभ
ओटज़िएई

@Otziii यह धागा पहली बार 2015 में लिखा गया था। पहले उत्तर में 259 वोट थे और इसे स्वीकार कर लिया गया था। मुझे नहीं लगता कि इसके उत्तर को जोड़ना आवश्यक है।
सॉलिडक

2
@ मुझे हाल ही में यह समस्या हुई थी, मैंने सभी उत्तरों की कोशिश की और केवल एक चीज जिसने इसे काम किया वह था जो मैंने अब टिप्पणी की। मेरे पास इस धागे पर एक उत्तर था, लेकिन यह सिर्फ नीचे की ओर निकला, इसलिए मैंने इसे एक टिप्पणी में बदल दिया। लोगों को लगता है कि यह समस्या अभी भी है, और किसी ने भी सफाई और पुनः आरंभ करने का उल्लेख नहीं किया है।
ओटज़िएई

जवाबों:


443

कोटलिन सिंथेटिक गुण जादू नहीं हैं और बहुत सरल तरीके से काम करते हैं। जब आप पहुंचते हैं btn_K, तो यह कॉल करता है getView().findViewById(R.id.btn_K)

समस्या यह है कि आप इसे जल्द ही एक्सेस कर रहे हैं। getView()में लौटता nullहै onCreateView। इसे onViewCreatedविधि में करने का प्रयास करें :

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    btn_K.setOnClickListener { Log.d(TAG, "onViewCreated(): hello world"); }
}

2
इसने काम कर दिया!! धन्यवाद। भविष्य के संदर्भ के लिए बस एक त्वरित सिर-अप। मेरे पास एक और अपवाद था, और मैंने थोड़ा गहरा खोदा और यह पता चला कि नल संदर्भ अपवाद यूआईएन थ्रेड से यूआई थ्रेड में आ रहा है जहां यह सिंथेटिक संपत्ति तक पहुंचने की कोशिश करेगा, लेकिन यह पहले से ही शून्य था। सुरक्षित कॉल ऑपरेटर (?) या कुछ अन्य शून्य सुरक्षा ऑपरेटर का उपयोग करना सुनिश्चित करें । यह दृश्य के एक वर्ग के संदर्भ को रखने में मदद करेगा और सिंथेटिक गुणों पर बाहर भरोसा नहीं onViewCreated()
करेगा

2
हालांकि एक सवाल - यह गतिविधि और अलगाव के लिए अलग कोड बनाता है? यदि हम एक अन्य संरचना का उपयोग करते हैं जिसमें getView()यह शामिल नहीं है या यह आह्वान नहीं कर सकती है findViewById(), तो क्या इसके आसपास काम करने का एक तरीका है? उदाहरण के लिए, यह सिखाएं कि कौन सा फ़ंक्शन मेरा लेआउट लौटाएगा?
मीलो

7
आप इसे भी एक्सेस कर सकते हैं जैसे rootView.btn_Kकि यदि आपके पास एक दृश्य है (और न केवल टुकड़ों में, यह हर जगह किया जा सकता है)
Adib Faramarzi

यह काम करता हैं ! हालाँकि, इसे कोटलिन प्रलेखन से अधिक रेखांकित किया जाना चाहिए। मैंने इस पोस्ट तक इस विधि को नोटिस नहीं किया .. वैसे भी धन्यवाद!
sokarcreative

2
मैंने हमेशा इसे onViewCreated में उपयोग किया, लेकिन फिर भी कुछ डिवाइस पर (मुझे क्रैशलाईटिक्स से रिपोर्ट मिली) इसे "शून्य नहीं होना चाहिए" अपवाद मिला। नजारा है। मैं सही लेआउट को बढ़ाता हूं, यह मेरे डिवाइस पर काम करता है। यह सिर्फ यादृच्छिक डिवाइस पर काम नहीं कर अजीब है।
आर्य अगुंग

9

आप इसे btn_Kबहुत जल्द कॉल कर रहे हैं क्योंकि उस समय यह एक अशक्त रिटर्न देता है और आपको Null Pointer Exception दे रहा है।

आप इस सिंथेटिक प्लगइन द्वारा इन विचारों का उपयोग कर सकते हैं onActivityCreated(), जिसे onCreateView()फ्रैगमेंट जीवनचक्र के ठीक बाद कहा जाता है ।

onActivityCreated()
{
        super.onActivityCreated(savedInstanceState)
        btn_K.setOnClickListener{}
}

मैं केवल यह बताना चाहता हूं कि कुछ कारणों से, इस उत्तर ने मेरे लिए काम किया जबकि स्वीकृत उत्तर नहीं दिया। मेरे विचार अशक्त हैं, onViewCreatedलेकिन फिर में परिभाषित किया गया है onActivityCreated। हालांकि पता नहीं क्यों।
नाथनएल

6

द्वारा उत्पन्न सिंथेटिक गुण Kotlin एंड्रॉयड एक्सटेंशन प्लगइन एक की जरूरत viewके लिए Fragment/Activityपहले से स्थापित किया जाना।

आपके मामले में, इसके लिए Fragment, आपको उपयोग करने की आवश्यकता view.btn_KहैonViewCreated

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    super.onCreateView(inflater, container, savedInstanceState)
    val view = inflater.inflate(R.layout.fragment_card_selector, container, false)
    view.btn_K.setOnClickListener{} // access with `view`
    return view
}

या बेहतर, आपको केवल सिंथेटिक गुणों में प्रवेश करना चाहिए onViewCreated

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    super.onCreateView(inflater, container, savedInstanceState)
    return inflater.inflate(R.layout.fragment_card_selector, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    btn_K.setOnClickListener{} // access without `view`
}

कृपया ध्यान दें कि savedInstanceStateपैरामीटर अशक्त होना चाहिए Bundle?, और सिंथेटिक गुणों को आयात करना भी जांचें

एक बार में विशिष्ट लेआउट के लिए सभी विजेट गुणों को आयात करना सुविधाजनक है:

import kotlinx.android.synthetic.main.<layout>.*

इस प्रकार यदि लेआउट फ़ाइल नाम गतिविधि_main.xml है, तो हम आयात करेंगे kotlinx.android.synthetic.main.activity_main.*.

यदि हम सिंथेटिक गुणों को व्यू पर कॉल करना चाहते हैं, तो हमें भी आयात करना चाहिए kotlinx.android.synthetic.main.activity_main.view.*.


3

केवल एक चीज जो आपको करने की आवश्यकता है:

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    var rootView = inflater?.inflate(R.layout.fragment_card_selector, container, false)
    rootView.btn_K.setOnClickListener { Log.d(TAG, "onViewCreated(): hello world"); }

    return rootView
}

1
हाँ, बस उपयोग करें val view = inflater.inflate() view.button.text = "caption"
कूलमाइंड

यह सबसे अच्छा जवाब है - सुनिश्चित करने के लिए सबसे साफ समाधान!
कैशेमेउटसाइड

@CacheMeOutside no, क्योंकि यह अभी भी बॉयलरप्लेट कोड है rootView.subView.doSomething। यह उपयोगकर्ता से शुरू होने वाले दृश्यों का उपयोग करने के लिए बेहतर हैonViewCreated
user924

3

साथी ऑब्जेक्ट को परिभाषित करने की आवश्यकता नहीं है, जैसे हर आईडी को एक दृश्य द्वारा कॉल करें

 lateinit var mView: View
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    mView=inflater.inflate(R.layout.product_list,container,false)

    mView.addProduct.setOnClickListener {

        val intent=Intent(activity,ProductAddActivity::class.java)
        startActivity(intent)
    }     return mView
}

1

Fragments में कृपया अपना कोड onActivity में लिखें: -

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        super.onCreateView(inflater, container, savedInstanceState)
        return inflater.inflate(R.layout.login_activity, container, false)

    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        callbackManager = CallbackManager.Factory.create()
        initialization()
        onClickLogin()
        onClickForgot()
        onClickSocailLogIn()

  }

1
क्यों? यह ज्ञान कहाँ है? onViewCreatedइसके बजाय क्यों नहीं ?
कुज्डू

0

मेरे मामले में कुछ भी काम नहीं किया जब तक कि मैंने टिप्पणियों में ओटज़िएई से सलाह का पालन नहीं किया । स्वच्छ, पुनर्निर्माण (कोई पुनरारंभ आवश्यक), एप्लिकेशन को फिर से चलाएँ। मुझे भी साथ जाने की जरूरत नहीं थी onActivityCreatedऔर बस onCreateViewचाल चली ।

एक बार मैंने गलत लेआउट को भड़काने की त्रुटि भी की, इस प्रकार स्पष्ट रूप से अपेक्षित नियंत्रण नहीं मिला।


मैंने इसे onActivityCreatedभी होते हुए देखा है
Jemshit Iskenderov

0

इसे @Egor नेलुबा के उत्तर में जोड़ते हुए, हाँ जब भी आप बिना संदर्भ के एक दृश्य को कॉल करते हैं, तो kotlinex एक rootView के लिए दिखता है, और जब से आप एक खंड के अंदर हैं और खंड में getView()विधि नहीं है । इसलिए यह फेंक सकता हैNullPointerException

इसे दूर करने के दो तरीके हैं,

  • या तो आप onViewCreated()उल्लेख के रूप में ओवरराइड करते हैं
  • या यदि आप किसी अन्य वर्ग (जैसे गुमनाम) में विचारों को बांधना चाहते हैं, तो आप बस इस तरह से एक विस्तार समारोह बना सकते हैं,

    fun View.bindViews(){...}

दूसरा दृष्टिकोण सहायक होता है, जब आपके पास एक से अधिक व्यवहार वाला एक ही टुकड़ा होता है।


-2
class CardSelectorFragment : Fragment() {


val TAG = javaClass.canonicalName

companion object {
    fun newInstance(): CardSelectorFragment {
        return CardSelectorFragment()
    }
}

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    var rootView = inflater?.inflate(R.layout.fragment_card_selector, container, false)

    rootView?.findViewById<TextView>(R.id.mTextView)?.setOnClickListener{
        Log.d(TAG, "onViewCreated(): hello world");
    }
    //btn_K.setOnClickListener { Log.d(TAG, "onViewCreated(): hello world"); }
    return rootView
}

}

** यहां आप btn_K.setOnClickListener को खोजने से पहले उपयोग कर रहे हैं-आपको अपने java / kotlin कोड में तत्व फॉर्म xml को फिर findViewById का उपयोग करके ढूंढना होगा और उसके बाद ही आप इस दृश्य या तत्व पर ऑपरेशन कर सकते हैं।

-इसलिए कि आपको मिला है पॉल्‍चर प्‍लानर

**

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