59

Can anyone help me to find out what can be the issue with this program. In the onCreate() method the findViewById() returns null for all ids and this causes a null pointer exception later. I can not figure out why the findViewById() can not find the view. Any suggestions?

This is the main code:

public class MainActivity extends Activity {

    ViewPager pager;
    MyPagerAdapter adapter;
    LinearLayout layout1, layout2, layout3;

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

        layout1 = (LinearLayout) findViewById(R.id.first_View);
        layout2 = (LinearLayout) findViewById(R.id.second_View);
        layout3 = (LinearLayout) findViewById(R.id.third_View);

        adapter = new MyPagerAdapter();
        pager = (ViewPager) findViewById(R.id.main_pager);
        pager.setAdapter(adapter);
    }

    private class MyPagerAdapter extends PagerAdapter
    {

        @Override
        public int getCount() { 
            return 3;
        }

        @Override
        public Object instantiateItem(ViewGroup collection, int position) {

            LinearLayout l = null;

            if (position == 0 )
            {
                l = layout1;
            }
            if (position == 1)
            {
                l = layout2;
            }

            if (position == 2)
            {
                l = layout3;
            }
                collection.addView(l, position);
                return l;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return (view==object);
        }

         @Override
         public void destroyItem(ViewGroup collection, int position, Object view) {
                 collection.removeView((View) view);
         }
    }
}

And the related XML files:

activity_main layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:orientation="vertical"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:background="#a4c639">


    <android.support.v4.view.ViewPager
                        android:layout_width="match_parent" 
                        android:layout_height="match_parent" 
                        android:id="@+id/main_pager"/>
</LinearLayout>

activity_first layout:

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

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_world" />

<Button
    android:id="@+id/button1"
    style="?android:attr/buttonStyleSmall"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Button" />

</LinearLayout>

activity_second layout:

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

android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/second_View">

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_world" />

</LinearLayout>

And the activity_third layout:

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

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_world" />

</LinearLayout>
weston
  • 54,145
  • 21
  • 145
  • 203
user2629828
  • 685
  • 1
  • 8
  • 13

12 Answers12

92

findViewById() returns a View if it exists in the layout you provided in setContentView(), otherwise it returns null and that's what happening to you. Note that if you don't setContentView(), and don't have a valid view to findViewById() on, findViewById() will always return null until you call setContentView().

This also means variables in the top-level trigger an NPE, because they're called before onCreate(), and by extension, before setContentView(). See also the activity lifecycle

Example if you setContentView(R.layout.activity_first); and then call findViewById(R.id.first_View); it will return a View which is your layout.

But if you call findViewById(R.id.second_View); before setContentView(), it will return null since there is not a view in your activity_first.xml layout called @+id/second_View.

Zoe
  • 27,060
  • 21
  • 118
  • 148
Ahmad Dwaik 'Warlock'
  • 5,953
  • 5
  • 34
  • 56
  • I have included all layouts to the main layout and I have no null pointer exception anymore. Thanks for the tip. – user2629828 Sep 29 '13 at 14:01
  • 7
    When I used this on a different view other than the currently displaying view, that one appeared. To get over with that unwanted behavior, I referred the view without using setContentView as follows. layout1 = (LinearLayout) View.inflate(this, R.layout.first_View, null); Then to access anything inside it, I could use Button botton = (Button) layout1.findViewById(R.id.button1); Just adding so that it might be helpful to sombody. – isuru chathuranga Aug 24 '14 at 13:08
  • 1
    Why? What is the advantage of forcing us? – Niklas Rosencrantz Nov 21 '17 at 06:38
  • Then what's the solution to include the resource which is not provided in`setContentView()`. – Alston May 31 '19 at 12:20
3

Emphasis added

For those cases within an Activity class.

Activity.findViewById(int id)

Finds a view that was identified by the id attribute from the XML that was processed in onCreate(Bundle).


Otherwise, such as an Fragment, Adapter, a View from a LayoutInflater, etc.

View.findViewById(int id)

Look for a child view with the given id. If this view has the given id, return this view.


Either case,

Returns
The view if found or null otherwise.


Now, re-check your XML files. Make sure you put the right value into setContentView or inflater.inflate.

In the case of an Activity, call findViewById after setContentView.

Then, make sure there is a View you are looking for with android:id="@+id/..." in that layout. Make sure the + is at @+id, which will add the resource to the R.id values to ensure you can find it from Java.

Community
  • 1
  • 1
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
2

The views you're trying to get are not defined in your activity_main layout. You need to programmatically inflate the views you're trying to add to the pager.-

@Override
public Object instantiateItem(ViewGroup collection, int position) {
    LinearLayout l = null;

    if (position == 0) {
        l = (LinearLayout) View.inflate(this, R.layout.activity_first, null);
    }
    if (position == 1) {
        l = (LinearLayout) View.inflate(this, R.layout.activity_second, null);
    }
    if (position == 2) {
        l = (LinearLayout) View.inflate(this, R.layout.activity_third, null);
    }

    collection.addView(l, position);
    return l;
}
ssantos
  • 16,001
  • 7
  • 50
  • 70
2

Sometimes you need clean your project in Eclipse (Project - Clean..).

Vlad
  • 3,465
  • 1
  • 31
  • 24
  • that solved it for me - it's ridiculous that it's a manual step, and also that bugs compromise the id lookups. . I thought machines are always logical - what on Earth can compromise the code in such a way?! – Razvan_TK9692 Aug 11 '21 at 17:43
1

add those views to the pager adapter before accessing them.

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

    adapter = new MyPagerAdapter();
    pager = (ViewPager) findViewById(R.id.main_pager);
    pager.setAdapter(adapter);

    layout1 = (LinearLayout) findViewById(R.id.first_View);
    layout2 = (LinearLayout) findViewById(R.id.second_View);
    layout3 = (LinearLayout) findViewById(R.id.third_View);

}

in the pager adapter:

public Object instantiateItem(View collection, int position) {
    if(position == 0){
        View layout = inflater.inflate(R.layout.activity_first, null);

        ((ViewPager) collection).addView(layout);

        return layout;
    } 
    ... and so forth.

}

from here you can access them via findViewById.

nebulae
  • 2,665
  • 1
  • 19
  • 16
1

In my case, it was a stupid mistake on my part. I had written code in the OnCreate method but it was above the setContentView line of code. Once I moved my code below this line the application started working fine.

setContentView(R.layout.activity_main);
IKavanagh
  • 6,089
  • 11
  • 42
  • 47
Will Buffington
  • 1,048
  • 11
  • 13
0

What @Warlock said above is right , you should initial LinearLayout layout1, layout2, layout3 by the right way:

LinearLayout layout1 = (LinearLayout) View.inflate(this, R.layout.first_View, null);
LinearLayout layout2 = (LinearLayout) View.inflate(this, R.layout.second_View, null);
LinearLayout layout3 = (LinearLayout) View.inflate(this, R.layout.third, null);

wish my advise help you

ArronXY
  • 41
  • 4
0

In Android, findViewById(R.id.some_id) works when you are finding view in the layout set.

That is, if you have set a layout say:

setContentView(R.layout.my_layout);

Views can be found only in this layout (my_layout).

In your code layout1, layout2, layout3 all are three different layouts and they are not set to the activity.

MrLore
  • 3,759
  • 2
  • 28
  • 36
Charan
  • 942
  • 1
  • 6
  • 18
0

The findViewById method must find what is in the layout (which you called in the setContentView)

Vasily Kabunov
  • 6,511
  • 13
  • 49
  • 53
0

I have gotten this error today and it was so simple to clear, that I "facepalmed".

Just try to add the UI element to your layout xml File in your res/layout-port directory!!!

0

Use the adaptor, to inflate the layout, and based on the position you can search for the view.

override fun instantiateItem(collection: ViewGroup, position: Int) : ViewGroup {
    val inflater = LayoutInflater.from(mContext)
    val layout = inflater.inflate(mData[position], collection, false) as ViewGroup

    if(position == your_position) {
       val nameOfField: TextView = layout.findViewById(R.id.item_id)
    }
-1

This problem is also generated when you are having same name of many components in XML file. Even if they are different layout files you should give every element a unique name. This error occur because you are having a XML element with the same name in another layout file and android studio is trying to access that and showing this error