从DialogFragment子类调用findViewById()会产生NullPointerException

时间:2014-12-01 00:12:18

标签: android view nullpointerexception findviewbyid dialogfragment

在下面的代码中,我尝试在单击按钮时显示基本对话框。该对话框显示了一些显示某些文本的需求。我在错误地解决了问题后得到了它,但我仍然有一个问题,为什么会发生错误。 在DialogFragmentSubclass.onCreateView()中,我通过调用findViewById(R.id.someIdValue)获得对TextView的引用。这给了我NullPointerException。但是,通过调用来获取引用:

View v = inflate.inflate(someREsourceValue, container, fals);
TextView tv = (TextView) v.findViewById(R.id.someValue);

似乎可以解决问题。为什么这个工作,另一个给我一个NullPointerException? (见下面的完整代码)

public class MainActivity extends Activity {
    DownloadImageDialogFragment myDialog;   

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

        // get reference to buttons
        Button buttonDownloadImage = (Button) findViewById(R.id.downloadImage);
        buttonDownloadImage.setText("Download new Image");

        // upon button click, show a Dialog
        buttonDownloadImage.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                FragmentTransaction ft = getFragmentManager().beginTransaction();

                myDialog = new DownloadImageDialogFragment();
                myDialog.show(ft, null);            
            }
        });

    }

    private class DownloadImageDialogFragment extends DialogFragment {              
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {

                View v = inflater.inflate(R.layout.fragment_dialog, container, false);
                // TextView tv = findViewById(R.id.dialogTextView); // this gives an error
                TextView tv = (TextView) v.findViewById(R.id.dialogTextView); // this works
                tv.setText("This is my dialog");
                return v;
            }
        }
}

在这里,对话框的布局文件:     

    <TextView 
        android:id="@+id/dialogTextView"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content" />

</LinearLayout>

2 个答案:

答案 0 :(得分:1)

当你打电话给findViewById()时,你是从Activity的内部类开始的,这是这个方法的来源。由于该视图ID在您的活动布局中不存在,因此您将获得null。您的对话框片段必须在其获取其中定义的视图之前对其布局(如您所找到的)进行充气。

答案 1 :(得分:0)

要解释这一点,你真的需要了解一个视图是什么。

根据Android website视图,

占据屏幕上的矩形区域,负责绘图和事件处理。 View是窗口小部件的基类,用于创建交互式UI组件(按钮,文本字段等)。 ViewGroup子类是布局的基类,它是包含其他视图(或其他ViewGroups)并定义其布局属性的不可见容器。

本质上它是一个阶级。它扩展了Object(java基类)并实现了Drawable.Callback KeyEvent.Callback AccessibilityEventSource。如果您对JAVA不感兴趣,请阅读this以了解implementsextends

现在,如果您阅读findViewById(...)函数,您将看到该函数返回一个View对象。这是 NOT 一个Textview对象。所以只有你应该知道你需要做一些额外的步骤来使代码库工作。

现在,如果您深入研究并阅读TextView Android页面,您会看到它扩展了View类。所以它继承了该类的所有内容。这就是为什么你需要将“type”传递给findViewById(int id)函数返回的View的原因。

最后,所有关于你从哪里调用你的函数。如果从没有定义View的Activity布局调用函数,则会像您一样获得NULL指针异常。我相信在这种情况下,您从子活动调用该函数,该子活动具有自己的xml并且没有定义textview。因此,您必须给拥有它的视图充气。添加TextView标记即可。