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