【问题标题】:Fragment getView().findViewById(R.id.box1) Returning null片段 getView().findViewById(R.id.box1) 返回 null
【发布时间】:2014-04-30 22:46:15
【问题描述】:

所以这就是问题所在。我正在编写一个应用程序,其中一个片段和一个按钮中有两个 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>

【问题讨论】:

  • 发布相关的xml和stacktrace
  • 你能发布你的代码吗?
  • 是的,对不起。在这里。
  • @Cybran 这个setBox1Text(String text) 叫什么名字?我的意思是点击哪个按钮,按钮在哪里?
  • 从持有fragment的Activity调用。等等,我也补充一下。

标签: android nullpointerexception fragment


【解决方案1】:

使用示例:

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

【讨论】:

  • 您好,欢迎您。这个答案有点稀疏 - 通常,如果可能的话,您需要添加一些评论并为提问者演示。
  • 我更新了答案,我认为这很公平。我测试了它,它工作正常
【解决方案2】:

确保在调用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));

【讨论】:

  • 我的问题是那行代码在 Activity 的 onViewCreated 中执行得很好。但是,当调用 setBox1Text 时,由于某种原因,box1 为 null。
  • @Cybran 似乎片段未附加到活动并且 getView 返回 null
  • @Cybran 在 onCreateView 中初始化并在setBox1Text(String text) 中使用它,并确保在片段附加到活动时调用它。检查if(framgent.isAdded())然后调用方法
  • @Cybran 您可以在创建活动并处于Resumed 状态时与按钮进行交互。所以当时附加了片段。 developer.android.com/guide/components/fragments.html。查看处理片段生命周期。只需在 onCreateview 中初始化它。 Resumed 片段在正在运行的 Activity 中可见。
【解决方案3】:

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

如果您检查您的代码,box1 和 box2 为 null 的唯一方法是尚未调用 onCreateView,所以当您这样做时

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

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

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

1-

使用工厂来初始化你的fragment,android中的fragment需要空的构造函数,所以这样你将使用一个空的构造函数,并确保你自己在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(); 
    }
}

【讨论】:

  • Box1 在 onCreateView() 中被初始化并且有效。但是由于某种原因,当我在单击按钮时尝试更改文本时,它会变为 null。
  • 你声明的变量不能被父类设置为null。您的问题是 onCreateView 没有在 fragment.show() 之后立即执行,因此您需要确保 onCreateView 已完成更新您的 UI,您可以按照我的回答(已编辑)或仅将日志添加到您的方法和检查订单
【解决方案4】:

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

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

你也可以试试cleaning the project

【讨论】:

  • 根据文档,Context没有这样的方法。
  • @Cybran 为什么要再次重新初始化editext,从哪里调用该方法?哪个按钮,按钮在哪里?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-15
  • 1970-01-01
  • 1970-01-01
  • 2013-10-07
  • 2021-11-23
相关资源
最近更新 更多