Android 在两个片段之间传递数据:NullPointerException

Android 在两个片段之间传递数据:NullPointerException,android,android-fragments,Android,Android Fragments,我有一个活动,它承载两个片段。一个包含EditText,另一个在GridView中显示输入Fragment1实现一个界面,当用户想要保存输入时通知用户。在活动中我想将数据传递到Fragment2的ArrayAdapter,但这里我得到了NullPointerException 活动: public class SwipeTest extends FragmentActivity implements TestFragment1

我有一个
活动
,它承载两个
片段
。一个包含
EditText
,另一个在
GridView
中显示输入
Fragment1
实现一个界面,当用户想要保存输入时通知用户。在
活动中
我想将数据传递到Fragment2的
ArrayAdapter
,但这里我得到了
NullPointerException

活动:

public class SwipeTest extends FragmentActivity implements TestFragment1
                                                               .OnFragmentInteractionListener {

    private final String[] tabs = {"Test 1", "Test 2"};
    private ViewPager        pager;
    private ActionBar        actionBar;
    private TabsPagerAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.pager = new ViewPager(this);
        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup
                                                                       .LayoutParams.MATCH_PARENT,
                                                                   ViewGroup
                                                                       .LayoutParams.MATCH_PARENT);
        this.pager.setLayoutParams(params);
        setContentView(this.pager);

        this.actionBar = getActionBar();
        this.adapter = new TabsPagerAdapter(
            getSupportFragmentManager());

        this.pager.setAdapter(this.adapter);
        this.actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        setUpViewPager();
        setUpActionBar();

    }

    /**
     * Sets up the ViewPager and adds an OnPageChangeListener
     */
    private void setUpViewPager() {
        this.pager.setAdapter(this.adapter);
        // pager needs an id; crashes if it has none
        this.pager.setId(123456789);

        // Set up the listener
        ViewPager.OnPageChangeListener onPageChangeListener = new ViewPager
            .OnPageChangeListener() {
            @Override
            public void onPageScrolled(int i, float v, int i2) {
            }

            @Override
            public void onPageSelected(int i) {
                SwipeTest.this.actionBar.setSelectedNavigationItem(i);
            }

            @Override
            public void onPageScrollStateChanged(int i) {
            }
        };

        this.pager.setOnPageChangeListener(onPageChangeListener);
    }

    /**
     * Sets up the ActionBar with it's tabs and adds an ActionBar.TabListener to
     * them
     */
    private void setUpActionBar() {
        this.actionBar = getActionBar();
        this.actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        // Set up listener
        ActionBar.TabListener tabListener = new ActionBar.TabListener() {
            @Override
            public void onTabSelected(ActionBar.Tab tab,
                                      FragmentTransaction
                                          fragmentTransaction) {
                SwipeTest.this.pager.setCurrentItem(tab.getPosition());
            }

            @Override
            public void onTabUnselected(ActionBar.Tab tab,
                                        FragmentTransaction
                                            fragmentTransaction) {
            }

            @Override
            public void onTabReselected(ActionBar.Tab tab,
                                        FragmentTransaction
                                            fragmentTransaction) {
            }
        };

        for (String tab_name : this.tabs) {
            this.actionBar.addTab(
                this.actionBar.newTab()
                              .setText(tab_name)
                              .setTabListener(tabListener));
        }
    }

    /**
     * Interface method of Fragment1
     */
    @Override
    public void onFragmentInteraction(String s) {
        // This gets the fragment correct
        TestFragment2 fragment = (TestFragment2) ((TabsPagerAdapter) pager
            .getAdapter()).getItem(1);
        // This assigns null to adapter
        ArrayAdapter<String> adapter = (ArrayAdapter<String>) fragment
            .getAdapter();
        adapter.add(s);
        adapter.notifyDataSetChanged();
    }


    public class TabsPagerAdapter extends FragmentPagerAdapter {

        public TabsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int index) {

            switch (index) {
                case 0:
                    return new TestFragment1();
                case 1:
                    return new TestFragment2();
            }

            return null;
        }

        @Override
        public int getCount() {
            return 2;
        }

    }
}
片段2:

public class TestFragment2 extends Fragment {

    private final List<String> data = new ArrayList<String>();
    private ArrayAdapter<String> adapter;

    public TestFragment2() {
        // Required empty public constructor
    }

    public ArrayAdapter getAdapter() {
        return this.adapter;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        GridView view = new GridView(getActivity());
        GridView.LayoutParams params = new AbsListView.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT);
        view.setLayoutParams(params);

        this.data.add("Hello");
        this.data.add("World");

        this.adapter = new ArrayAdapter(getActivity(),
                                        android.R.layout
                                            .simple_list_item_1,
                                        this.data);
        view.setAdapter(this.adapter);

        return view;
    }


}
公共类TestFragment2扩展了片段{
私有最终列表数据=新的ArrayList();
专用阵列适配器;
公共测试片段2(){
//必需的空公共构造函数
}
公共阵列适配器getAdapter(){
返回此.adapter;
}
@凌驾
创建视图上的公共视图(布局、充气机、视图组容器、,
Bundle savedInstanceState){
GridView=newGridView(getActivity());
GridView.LayoutParams params=新的AbsListView.LayoutParams(
ViewGroup.LayoutParams.MATCH_父级,
ViewGroup.LayoutParams.MATCH_PARENT);
view.setLayoutParams(参数);
this.data.add(“Hello”);
本.数据.添加(“世界”);
this.adapter=new ArrayAdapter(getActivity(),
android.R.布局
.simple_list_item_1,
这是数据);
view.setAdapter(this.adapter);
返回视图;
}
}

我不知道为什么
ArrayAdapter adapter=(ArrayAdapter)fragment.getAdapter()为空。那么,如何访问Fragment2的字段呢?

如果寻呼机从未显示过第二个片段,当调用fragment1接口回调时,寻呼机返回null:

// This gets the fragment correct
TestFragment2 fragment = (TestFragment2) ((TabsPagerAdapter) pager
    .getAdapter()).getItem(1);

因此,您随后对
getAdapter()
的调用将导致NPE。

这似乎是关于生命周期的问题。您可能知道,onCreateView()是异步方法,所以可以在setAdapter()之前访问片段实例


我的建议是在SwipTest#onCreate()中创建TestFragment2实例。此外,每次按下按钮时,代码都会创建新实例。这似乎不是个好主意。

问题出在
PagerAdapter
中。我使用
getItem()
接收绑定到选项卡位置的
片段。错误在于我返回了该
片段的一个新实例,而不是返回现有的
片段。由于新的
片段
从未显示过
片段
onCreateView()
,因此从未调用
setUpAdapter()
。这就是为什么我收到了
NPE
in

ArrayAdapter<String> adapter = (ArrayAdapter<String>) fragment
    .getAdapter();
adapter.add(s);
ArrayAdapter适配器=(ArrayAdapter)片段
.getAdapter();
适配器。添加(s);
方法[*]:

public class TabsPagerAdapter extends FragmentPagerAdapter {
    private final List<Fragment> mFragments = new ArrayList<Fragment>();

    public TabsPagerAdapter(FragmentManager fm) {
        super(fm);
        mFragments.add(0, new TestFragment1());
        mFragments.add(1, new TestFragment2());
    }

    @Override
    public Fragment getItem(int index) {
        if (index > (mFragments.size() - 1) )
            return null;
        return mFragments.get(index);
    }

    @Override
    public int getCount() {
        return mFragments.size();
    }

}
公共类选项卡SpagerAdapter扩展了FragmentPagerAdapter{
私有最终列表MFFragments=new ArrayList();
公共选项卡SpagerAdapter(FragmentManager fm){
超级(fm);
添加(0,新的TestFragment1());
添加(1,新的TestFragment2());
}
@凌驾
公共片段getItem(int索引){
如果(索引>(mffragments.size()-1))
返回null;
返回mffragments.get(索引);
}
@凌驾
public int getCount(){
返回mffragments.size();
}
}

[*]未经测试,因为我更改了代码,不再使用
PagerAdapter
,但我认为解决方案是可以理解的。

这是不正确的。如果我添加
System.out.println(片段)
系统输出打印LN(适配器)
适配器之前添加输出为:
I/System.out﹕ TestFragment2{3c032a82}I/System.out﹕ 空| D/AndroidRuntime﹕ 关闭VM | E/AndroidRuntime﹕ 致命异常:主(NPE)
。因此
getItem(1)
提供了一个正确的
TestFragment2
对象,但是
getAdapter()
提供了空值仔细检查fragment2的生命周期。如果您得到的是片段而不是适配器,则fragment2中的onCreateView方法尚未调用,否则适配器将为非null。令人困惑的是,
onCreateView
已被调用。我添加了
System.out.println(“onCreateView”)
System.out.println(这个.adapter)(在
this.adapter=new…
之后)在
Fragment2 onCreateView
中的语句。结果是:Fragment2 OnTach | Fragment2 onCreateView | Fragment2适配器已初始化:android.widget。ArrayAdapter@302ed58d| TestFragment2{a369af9}| getAdapter():null |关闭VM |致命异常:main您可以为整个logcat输出提供堆栈转储吗?这里有些不对劲。谢谢你的回答。前一段时间我自己解决了这个问题,但我忘了在这里发布解决方案。你们答案的第二段是一种解决方案。我解释了我在回答中犯的错误。
public class TabsPagerAdapter extends FragmentPagerAdapter {
    private final List<Fragment> mFragments = new ArrayList<Fragment>();

    public TabsPagerAdapter(FragmentManager fm) {
        super(fm);
        mFragments.add(0, new TestFragment1());
        mFragments.add(1, new TestFragment2());
    }

    @Override
    public Fragment getItem(int index) {
        if (index > (mFragments.size() - 1) )
            return null;
        return mFragments.get(index);
    }

    @Override
    public int getCount() {
        return mFragments.size();
    }

}