片段getView()。findViewById(R.id.box1)返回null

时间:2014-03-23 18:01:43

标签: android nullpointerexception fragment

所以这就是问题所在。我正在使用片段和按钮内的两个EditText视图编写应用程序。单击该按钮时,它会更改EditText的文本。在onViewCreated()方法中,我使用此代码获取EditText实例并将其存储到变量中。

EditText box1 = (EditText)(getView.findViewById(R.id.box1));

这很好用。但是,当我单击按钮时尝试访问变量box1时,EditText变为null并抛出NullPointerException。有谁知道为什么会这样?

这是片段代码:

public class MyFragment extends Fragment {

EditText box1, box2;

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

        //Works here.
        box1 = (EditText)(rootView.findViewById(R.id.box1));
        box2 = (EditText)(rootView.findViewById(R.id.box2));
        //Same thing. Sets the text correctly
        box1.setText("hey look at me!");
        return rootView;
    }

    //Called when the button is clicked.
    public void setBox1Text(String text) {
        //It's null here so it skips to the else
        if(box1 != null) {
            box1.setText(text);
        }
        else {
            //This doesn't work. Throws the exception here.
            box1 = (EditText)(getView().findViewById(R.id.box1));
        }
    }

    public void setBox2Text(String text) {
        if(box2 != null) {
            box2.setText(text);
        }
        else {
            //This doesn't work. Throws the exception here.
            box2 = (EditText)(getView().findViewById(R.id.box2));
        }
    }

    public String getBox1Text() {
        if(box1 == null) {
            return "Nice try.";
        }
        return box1.getText().toString();
    }

    public String getBox2Text() {
        if(box2 == null) {
            return "Nice try.";
        }
        return box2.getText().toString();
    }
}

这是包含片段的活动:

public class MyActivity extends Activity {

    MyFragment myFragment
    EditText box1, box2;

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

        if (savedInstanceState == null) {
            myFragment = new MyFragment();
            getFragmentManager().beginTransaction()
                    .add(R.id.container, myFragment.commit();
        }

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.my_app, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }


    public void box1Click(View v) { 
        myFragment.setBox2Text("Some text");
    }

    public void box2Click(View v) {
        myFragment.setBox2Text("Some text");
    }

}

以下是片段中的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="com.mycode.MyFragment" >

<EditText
    android:id="@+id/box1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:inputType="textMultiLine" />
<EditText
    android:id="@+id/box2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@id/box1"
    android:inputType="textMultiLine|none"
    android:focusable="false" />
<Button
    android:id="@+id/button2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/box2"
    android:layout_alignParentRight="true"
    android:onClick="box2Click" />
<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/encrypt_button_text"
    android:layout_below="@id/box2"
    android:layout_toLeftOf="@id/button2"
    android:onClick="box1Click" />

</RelativeLayout>

4 个答案:

答案 0 :(得分:4)

使用示例:

public class main extends Fragment{

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.core_info_tab, container, false);
        ImageButton ib = (ImageButton) view.findViewById(R.id.imageButton1);
        return view;
    }
}

答案 1 :(得分:0)

那是因为您在创建片段之前尝试执行setBoxXText(...)onCreateView尚未执行。在访问它的视图之前,请确保已加载您的片段。

如果你检查你的代码,唯一的方法是box1&amp; box2为null是尚未调用onCreateView,所以当你执行

if(box1 != null) {
            box1.setText(text);
        }
        else {

并且它通过else语句,因为你没有初始化片段。

您有几种方法可以解决此问题,例如,您可以在片段初始化(1)中设置此值,或使用侦听器通知何时加载片段(2)。

1-

使用工厂初始化你的片段,android中的片段需要空构造函数,所以这样你就会使用一个空的构造函数,并确保你自己在onCreateView中设置了box1和box2字符串

public class YourFragment extends Fragment{

    //Empty and private constructor
    private YourFragment(){

    }

    private String box1Text;
    private String box2Text;

    public void setBox1Text(String box1Text){
        this.box1Text = box1Text;
    }

    public void setBox2Text(String box2Text){
        this.box2Text = box2Text;
    }

    public static YourFragment YourFragmentFactory(String box1Text, String box2Text){
        YourFragment result = new YourFragment();
        result.setBox1Text(box1Text);
        result.setBox2Text(box2Text);
        return result;
    }   
}

和2: 当您可以开始设置文本时,使用监听器通知您的活动:

public interface YourFragmentListener{

    public void onViewCreated();
}

private YourFragmentListener listener;

public void setListener(YourFragmentListener listener){
    this.listener = listener;
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onViewCreated(view, savedInstanceState);

    if(this.listener != null){
        this.listener.onViewCreated(); 
    }
}

答案 2 :(得分:0)

确保在调用setBox1Text(String text)之前将片段附加到活动上,否则视图未初始化且getView返回null。

无需再次初始化edittext。

你可以拥有

public void setBox1Text(String text) {       
        box1.setText(text); // box1 is already initialized in onCreate no need to initialize again
} 

如果您想使用getView,请在onActivtiyCreated

中使用它
 box1 = (EditText)getView().findViewById(R.id.box1));

答案 3 :(得分:-1)

要使用findViewById,您必须在Context执行它(例如Activity)。

使用:View.getContext().getViewById...

您还可以尝试cleaning the project