nullpointer在使用视图时从活动运行片段的方法

时间:2014-07-09 13:08:43

标签: android android-fragments

我的片段

public class CustomFrag extends Fragment {

    private Button btn;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.button_fragment, container, false);

        btn = (Button)view.findViewById(R.id.button1);

        return view;
    }
    public void sendItem(String item) {
        btn.setText(item);
    }
}

在我的活动中

public void loadFragment(String data) {
    // Load up new fragment
    Fragment fragment = new CustomFrag();
    FragmentManager fm = getSupportFragmentManager();
    FragmentTransaction transaction = fm.beginTransaction();

    transaction.add(R.id.contentFragment, fragment, "custFrag");
    transaction.addToBackStack("custFrag");
    transaction.commit();

    // Required before calling fragment methods 
    getSupportFragmentManager().executePendingTransactions();

    // Load fragment with data
    CustomFrag frag = (CustomFrag) getSupportFragmentManager().findFragmentByTag("custFrag");
    frag.sendItem(data);
}

每当我尝试使用片段的视图时,我都会得到一个nullpointer异常。如果我尝试加载方法内部的视图,它将无法正常工作

即。在sendItem()

btn = (Button)getView().findViewById(R.id.button1);

我的布局(button_fragment)包含按钮:

<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

2 个答案:

答案 0 :(得分:2)

因为您已经执行了事务并不意味着片段实际上已经创建了它的视图。这就是btn仍为空的原因。

要将数据从活动传递到片段,请使用参数bundle:

Fragment fragment = new CustomFrag();
Bundle args = new Bundle();
args.putString("item", data);
fragment.setArguments(args);

然后,在onCreateView

btn = (Button)view.findViewById(R.id.button1);
btn.setText(getArguments().getString("item"));

请参阅此Best practice for instantiating a new Android Fragment问题和第一个答案。

答案 1 :(得分:1)

这里的问题是,当调用sendItem(...)时,片段的布局还没有被绘制。这意味着btn在那时为空。相反,这就是你应该这样做的方式(见http://developer.android.com/guide/components/fragments.html):

public class CustomFrag extends Fragment {

    private Button btn;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.button_fragment, container, false);

        btn = (Button)view.findViewById(R.id.button1);
        btn.setText(getArguments.getString("item"));
        return view;
    }
}

public void loadFragment(String data) {
    // Load up new fragment
    Fragment fragment = new CustomFrag();
    Bundle args = new Bundle();
    args.putString("item", data);
    fragment.setArguments(args);

    FragmentManager fm = getSupportFragmentManager();
    FragmentTransaction transaction = fm.beginTransaction();

    transaction.add(R.id.contentFragment, fragment, "custFrag");
    transaction.addToBackStack("custFrag");
    transaction.commit();

    // Required before calling fragment methods 
    getSupportFragmentManager().executePendingTransactions();
}

编辑: njzk2更快,但我希望我给出的细节将进一步帮助你。无论如何,他给出的链接很好地解释了为什么你应该这样做。