NullPointerException onCreate () में विचारों तक पहुँचने


114

यह StackOverflow पर अक्सर पोस्ट की गई समस्या के लिए एक विहित प्रश्न है।

मैं एक ट्यूटोरियल का अनुसरण कर रहा हूं। मैंने एक विज़ार्ड का उपयोग करके एक नई गतिविधि बनाई है। मुझे अपनी गतिविधि में प्राप्त s NullPointerExceptionपर एक विधि को कॉल करने का प्रयास करते समय मिलता है ।ViewfindViewById()onCreate()

गतिविधि onCreate():

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

    View something = findViewById(R.id.something);
    something.setOnClickListener(new View.OnClickListener() { ... }); // NPE HERE

    if (savedInstanceState == null) {
        getSupportFragmentManager().beginTransaction()
                .add(R.id.container, new PlaceholderFragment()).commit();
    }
}

लेआउट XML ( fragment_main.xml):

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="packagename.MainActivity$PlaceholderFragment" >

    <View
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:id="@+id/something" />

</RelativeLayout>

जवाबों:


70

ट्यूटोरियल शायद पुराना है, विज़ार्ड-जनरेटेड कोड द्वारा पसंद किए गए खंड-आधारित UI के बजाय एक गतिविधि-आधारित UI बनाने का प्रयास करता है।

दृश्य खंड लेआउट ( fragment_main.xml) में है और गतिविधि लेआउट में नहीं है ( activity_main.xml)। onCreate()जीवन चक्र में गतिविधि दृश्य पदानुक्रम में इसे खोजने के लिए बहुत जल्दी है, और एक nullवापस आ गया है। nullएनपीई के कारणों पर एक विधि लागू करना ।

पसंदीदा समाधान कोड को टुकड़े में स्थानांतरित करने के लिए है onCreateView(), findViewById()फुलाए हुए टुकड़े लेआउट पर कॉल करना rootView:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
    Bundle savedInstanceState) {
  View rootView = inflater.inflate(R.layout.fragment_main, container,
      false);

  View something = rootView.findViewById(R.id.something); // not activity findViewById()
  something.setOnClickListener(new View.OnClickListener() { ... });

  return rootView;
}

एक साइड नोट के रूप में, फ़्रेग्मेंट लेआउट अंततः गतिविधि के साथ पदानुक्रम और खोज योग्य गतिविधि का एक हिस्सा होगा, findViewById()लेकिन केवल फ़्रेग्मेंट लेनदेन के चलने के बाद। लंबित विखंडन लेनदेन के super.onStart()बाद निष्पादित हो जाते हैं onCreate()


findViewById हिस्सा onActivityCreated होना चाहिए।
ज़ार ई अहमर

@ नीपर यह हो सकता है लेकिन ऐसा नहीं है।
लालाटो

कुछ समय के लिए गतिविधि अभी तक टुकड़े से जुड़ी नहीं है।
ज़ार ई अहमर

1
@Nepster और क्यों बुला कि के findViewById()पर rootViewऔर गतिविधि पर नहीं।
लालाटो

10

OnStart()विधि और बस उपयोग की कोशिश करो

View view = getView().findViewById(R.id.something);

या getView().findViewByIdविधि का उपयोग करके किसी भी दृश्य की घोषणा करेंonStart()

देखने के आधार पर श्रोता पर क्लिक करें anyView.setOnClickListener(this);


मेरे लिए यह उपयोगी था क्योंकि मैं खंड के onCreateView के अंदर एक भाई के दृश्य को देखने का प्रयास कर रहा था, जहां खंड को xml में घोषित किया गया था। अभिभावक विचार अभी भी onCreateView में अशक्त थे क्योंकि माता-पिता ने फुलाया नहीं था, लेकिन ऑनस्टार्ट में उनके पास :)
डैनियल विल्सन

3

अपने पहुंच विचारों को खंड के onViewCreated विधि में स्थानांतरित करने का प्रयास करें क्योंकि कभी-कभी जब आप onCreate पद्धति में विचारों को एक्सेस करने का प्रयास करते हैं, तो वे उस समय परिणामी नहीं होते हैं, जब अशक्त सूचक अपवाद होता है।

 @Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
     View something = findViewById(R.id.something);
     something.setOnClickListener(new View.OnClickListener() { ... }); // NPE HERE

     if (savedInstanceState == null) {
           getSupportFragmentManager().beginTransaction()
            .add(R.id.container, new PlaceholderFragment()).commit();
    }
 }

2

सहमत, यह एक विशिष्ट त्रुटि है क्योंकि लोग अक्सर समझ नहीं पाते हैं कि जब वे एंड्रॉइड विकास पर काम करना शुरू करते हैं तो फ्रेगमेंट कैसे काम करते हैं। भ्रम को कम करने के लिए, मैंने एक सरल उदाहरण कोड बनाया, जिसे मैंने मूल रूप से एप्लिकेशन पर पोस्ट किया है , एंड्रॉइड एमुलेटर में बंद है , लेकिन मैंने इसे यहां भी पोस्ट किया है।

एक उदाहरण निम्नलिखित है:

public class ContainerActivity extends FragmentActivity implements ExampleFragment.Callback
{
    @Override
    public void onCreate(Bundle saveInstanceState)
    {
        super.onCreate(saveInstanceState);
        this.setContentView(R.layout.activity_container);
        if (saveInstanceState == null)
        {               
             getSupportFragmentManager().beginTransaction()
                .add(R.id.activity_container_container, new ExampleFragment())
                .addToBackStack(null)
             .commit();
        }
        getSupportFragmentManager().addOnBackStackChangedListener(new OnBackStackChangedListener()
        {
            public void onBackStackChanged()
            {
                int backCount = getSupportFragmentManager().getBackStackEntryCount();
                if (backCount == 0)
                {
                    finish();
                }
            }
        });
    }

    @Override
    public void exampleFragmentCallback()
    {
        Toast.makeText(this, "Hello!", Toast.LENGTH_LONG).show();
    }
}

activity_container.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <FrameLayout
        android:id="@+id/activity_container_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

ExampleFragment:

public class ExampleFragment extends Fragment implements View.OnClickListener
{
    public static interface Callback
    {
        void exampleFragmentCallback();
    }

    private Button btnOne;
    private Button btnTwo;
    private Button btnThree;

    private Callback callback;

    @Override
    public void onAttach(Activity activity)
    {
        super.onAttach(activity);
        try
        {
            this.callback = (Callback) activity;
        }
        catch (ClassCastException e)
        {
            Log.e(this.getClass().getSimpleName(), "Activity must implement Callback interface.", e);
            throw e;
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View rootView = inflater.inflate(R.layout.fragment_example, container, false);

        btnOne = (Button) rootView.findViewById(R.id.example_button_one);
        btnTwo = (Button) rootView.findViewById(R.id.example_button_two);
        btnThree = (Button) rootView.findViewById(R.id.example_button_three);

        btnOne.setOnClickListener(this);
        btnTwo.setOnClickListener(this);
        btnThree.setOnClickListener(this);
        return rootView;
    }

    @Override
    public void onClick(View v)
    {
        if (btnOne == v)
        {
            Toast.makeText(getActivity(), "One.", Toast.LENGTH_LONG).show();
        }
        else if (btnTwo == v)
        {
            Toast.makeText(getActivity(), "Two.", Toast.LENGTH_LONG).show();
        }
        else if (btnThree == v)
        {
            callback.exampleFragmentCallback();
        }
    }
}

fragment_example.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <Button
            android:id="@+id/example_button_one"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="30dp"
            android:text="@string/hello" 
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"/>

        <Button
            android:id="@+id/example_button_two"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/example_button_one"
            android:layout_alignRight="@+id/example_button_one"
            android:layout_below="@+id/example_button_one"
            android:layout_marginTop="30dp"
            android:text="@string/hello" />

        <Button
            android:id="@+id/example_button_three"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/example_button_two"
            android:layout_alignRight="@+id/example_button_two"
            android:layout_below="@+id/example_button_two"
            android:layout_marginTop="30dp"
            android:text="@string/hello" />

</RelativeLayout>

और यह एक मान्य उदाहरण होना चाहिए, यह दिखाता है कि आप किसी गतिविधि का उपयोग करके किसी फ़्रैगमेंट को कैसे प्रदर्शित कर सकते हैं, और उस फ़्रैगमेंट में घटनाओं को संभाल सकते हैं। और युक्त गतिविधि के साथ संवाद कैसे करें।


1
यह उदाहरण FragmentActivity और समर्थन टुकड़े प्रबंधक के लिए android-support-v4 लाइब्रेरी का उपयोग करता है।
इपिकपांडेफर्स

1
एक और भी पूरा उदाहरण stackoverflow.com/questions/24840509/…
EpicPandaForce

1
यद्यपि आपको Ottoकॉलबैक के बजाय संचार के लिए उपयोग करना चाहिए , और Butterknifeविचारों को इंजेक्ट करने के लिए उपयोग करना चाहिए ।
एपिकपांडाफ़ोर्स

2

दृश्य "कुछ" खंड में है और गतिविधि में नहीं है, इसलिए गतिविधि में इसे एक्सेस करने के बजाय आपको इसे खंड श्रेणी में एक्सेस करना होगा

प्लेसहोल्डरफ्रैगमेंट.क्लास में

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_main, container,
  false);

View something = root .findViewById(R.id.something);
something.setOnClickListener(new View.OnClickListener() { ... });

return root;
}

2

आप यूआई तत्वों को एक्सेस करने की कोशिश कर रहे हैं onCreate()लेकिन, उन्हें एक्सेस करना बहुत जल्दी है, क्योंकि टुकड़े के विचारों को onCreateView()विधि में बनाया जा सकता है । और onActivityCreated()विधि उन पर किसी भी कार्रवाई को संभालने के लिए विश्वसनीय है, क्योंकि इस राज्य में गतिविधि पूरी तरह से भरी हुई है।


1

निम्नलिखित को अपनी गतिविधि में जोड़ें। main.xml

<fragment
    android:id="@+id/myFragment"
    android:name="packagename.MainActivity$PlaceholderFragment"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" >
</fragment>

0

चूँकि आपने अपना दृश्य घोषित कर दिया है fragment_main.xml, इसलिए उस टुकड़े को उस स्थान पर ले जाएँ जहाँ आपको onCreateView()खंड के तरीके में NPE मिलता है । इस मुद्दे को हल करना चाहिए।


0

प्रश्न में ऊपर पोस्ट कोड में एक समस्या है: आप oncreate विधि में R.layout.activity_main का उपयोग कर रहे हैं, लेकिन xml फ़ाइलों का नाम "fragment_main.xml" है, जिसका अर्थ है कि आप fragment_main.xml फ़ाइल का दृश्य प्राप्त करने का प्रयास कर रहे हैं जो नहीं दिखाया जा रहा है, इसलिए यह शून्य सूचक अपवाद देता है। जैसे कोड बदलें:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.fragment_main);// your xml layout ,where the views are

    View something = findViewById(R.id.something);
    something.setOnClickListener(new View.OnClickListener() { ... }); // NPE HERE

    if (savedInstanceState == null) {
        getSupportFragmentManager().beginTransaction()
                .add(R.id.container, new PlaceholderFragment()).commit();
    }
}

0

आपको महत्वपूर्ण बात याद रखनी है: NullPointerException तब होती है जब आपने अपना वैरिएबल घोषित किया है और इसके मूल्य को असाइन करने से पहले इसके मूल्य को पुनः प्राप्त करने की कोशिश कर रहा है।


0

उपयोग onViewCreated () विधि जब भी उपयोग कर या टुकड़े से विचारों बुला।

override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
      View v = view.findViewById(R.id.whatever)
}

0

मैंने NullPointerExceptionकॉलिंग findViewById() onCreate()और onCreateView()तरीकों के बाद एक श्रोता को एक ही आरंभिक रूप दिया है ।

लेकिन जब मैंने इसका उपयोग किया है तो onActivityCreated(Bundle savedInstanceState) {...}यह काम करता है। इसलिए, मैं GroupViewअपने श्रोता तक पहुंच सकता हूं और सेट कर सकता हूं।

मुझे उम्मीद है कि यह मददगार होगा।


0

विचारों को खोजने के लिए सबसे लोकप्रिय पुस्तकालय जो लगभग हर डेवलपर द्वारा उपयोग किया जाता है।

मक्खन काटने की छुरी

जैसा कि मैं कर सकता हूँ उनके पर्याप्त उत्तर हैं जो उचित कार्यप्रणाली के साथ विचार खोजने के लिए समझाते हैं। लेकिन अगर आप दैनिक आधार पर एंड्रॉइड डेवलपर और कोड हैं, तो आप मक्खन-चाकू का उपयोग कर सकते हैं जो विचारों को खोजने में बहुत समय बचाता है और आपके पास इसके लिए कोड नहीं है, 2-3 चरणों में आप मिलिसेकंड में विचार देख सकते हैं ।

एप्लिकेशन स्तर श्रेणी में निर्भरता जोड़ें:

implementation 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'

मक्खन चाकू के लिए प्लगइन जोड़ें:

File -> Settings -> plugins-> 

फिर Android ButterKnife Zelezny की खोज करें और प्लगइन इंस्टॉल करें और अपने स्टूडियो को पुनरारंभ करें और आप इसके साथ कर रहे हैं।

अब बस अपनी गतिविधि के Oncreate तरीके पर जाएं और अपने layout_name पर राइट क्लिक करें और जनरेट बटन पर टैप करें और बटरनाइफ़ इंजेक्शन विकल्प चुनें और आपके विचार संदर्भ स्वचालित रूप से नीचे दिए गए उल्लेख की तरह बनाए जाएंगे:

    @BindView(R.id.rv_featured_artist)
    ViewPager rvFeaturedArtist;
    @BindView(R.id.indicator)
    PageIndicator indicator;
    @BindView(R.id.rv_artist)
    RecyclerView rvArtist;
    @BindView(R.id.nsv)
    NestedScrollingView nsv;
    @BindView(R.id.btn_filter)
    Button btnFilter;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.