58

谁能帮我找出这个程序可能存在的问题。在该onCreate()方法中findViewById(),所有 id 都返回 null,这会导致稍后出现空指针异常。我不知道为什么findViewById()找不到视图。有什么建议么?

这是主要代码:

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);
         }
    }
}

以及相关的 XML 文件:

活动主布局:

<?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 布局:

<?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 布局:

 <?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>

还有 activity_third 布局:

<?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>
4

12 回答 12

89

findViewById()如果 View 存在于您提供的布局中,则返回一个 View setContentView(),否则它返回 null,这就是发生在您身上的事情。请注意,如果您不这样做setContentView(),并且没有有效的findViewById()on 视图,findViewById()将始终返回 null,直到您调用setContentView().

这也意味着顶级变量会触发 NPE,因为它们被调用 before onCreate(),并且通过扩展调用 before setContentView()。另请参阅活动生命周期

例如,如果您setContentView(R.layout.activity_first);然后调用findViewById(R.id.first_View);它将返回一个视图,即您的布局。

但是如果你之前调用findViewById(R.id.second_View);setContentView(),它会返回,因为你的布局null中没有一个视图叫做.activity_first.xml@+id/second_View

于 2013-09-29T13:21:42.043 回答
3

强调添加

对于 Activity 类中的那些情况。

Activity.findViewById(int id)

查找由在中处理的 XML 中id的属性标识的视图。onCreate(Bundle)


否则,例如 Fragment、Adapter、a Viewfrom aLayoutInflater等。

View.findViewById(int id)

寻找具有给定的子视图id。如果此视图具有给定的 id,则返回此视图。


无论哪种情况,

返回
视图(如果找到的null


现在,重新检查您的 XML 文件。确保将正确的值放入setContentViewor inflater.inflate

在 Activity 的情况下,调用findViewByIdafter setContentView

然后,确保android:id="@+id/..."在该布局中有您正在寻找的视图。确保+是 at @+id,这会将资源添加到R.id值中,以确保您可以从 Java 中找到它。

于 2016-11-10T23:04:31.583 回答
2

您尝试获取的视图未在您的activity_main布局中定义。您需要以编程方式扩展您尝试添加到寻呼机的视图。-

@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;
}
于 2013-09-29T13:25:35.187 回答
2

有时您需要在 Eclipse 中清理您的项目(Project - Clean..)。

于 2014-04-05T17:13:46.220 回答
1

在访问它们之前将这些视图添加到寻呼机适配器。

@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);

}

在寻呼机适配器中:

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.

}

从这里您可以通过 findViewById 访问它们。

于 2013-09-29T13:28:33.143 回答
1

就我而言,这是一个愚蠢的错误。我在 OnCreate 方法中编写了代码,但它在代码行之上setContentView。一旦我将代码移到此行下方,应用程序就开始正常工作。

setContentView(R.layout.activity_main);
于 2018-05-08T16:37:37.670 回答
1

使用适配器扩展布局,并根据位置搜索视图。

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)
    }
于 2021-11-12T17:30:05.127 回答
0

@Warlock上面说的没错,你应该用正确的方式初始化LinearLayout layout1,layout2,layout3:

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);

希望我的建议对你有帮助

于 2013-09-29T13:29:56.260 回答
0

在 Android 中,findViewById(R.id.some_id)当您在布局集中查找视图时有效。

也就是说,如果您设置了布局,请说:

setContentView(R.layout.my_layout);

只能在此布局 (my_layout) 中找到视图。

在您的代码layout1layout2layout3所有都是三种不同的布局,并且它们未设置为活动。

于 2013-09-29T13:34:49.447 回答
0

findViewById方法必须找到布局中的内容(您在 中调用setContentView

于 2013-09-29T13:59:20.060 回答
0

我今天收到了这个错误,而且很容易清除,以至于我“捂脸”。

只需尝试将 UI 元素添加到您的res/layout-port 目录中的布局 xml 文件中!!!

于 2014-05-26T09:51:44.127 回答
-1

当您在 XML 文件中具有相同名称的许多组件时,也会产生此问题。即使它们是不同的布局文件,您也应该给每个元素一个唯一的名称。发生此错误是因为您在另一个布局文件中有一个同名的 XML 元素,并且 android studio 正在尝试访问该元素并显示此错误

于 2021-06-01T18:03:37.153 回答