我有以下问题:
我对活动的操作栏有一个自定义布局,如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:divider="?android:attr/dividerVertical"
android:showDividers="middle"
android:dividerPadding="6dp">
<include layout="@layout/include_cancel_button" />
<include layout="@layout/include_done_button" />
</LinearLayout>
带有一个类似的按钮:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="?android:actionButtonStyle"
android:id="@+id/actionbar_done"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:onClick="saveSchwein" >
<TextView style="?android:actionBarTabTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingRight="10dp"
android:drawableLeft="@drawable/ic_action_ok"
android:drawablePadding="8dp"
android:gravity="center_vertical"
android:text="@string/ok" />
</FrameLayout>
该片段在活动的onCreate()期间添加到ViewPager中,如下所示:
viewPager = (ViewPager) findViewById(R.id.schweinpager);
tabPagerAdapter = new SchweinFragmentAdapter(getSupportFragmentManager());
viewPager.setAdapter(tabPagerAdapter);
actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name).setTabListener(this).setTag(tab_name));
}
到目前为止,一切正常。我在操作栏的选项卡中显示了三个片段,可以在它们之间滑动开关而不会出现问题。
现在是我的实际问题:我想在自定义操作栏中的片段中调用一个函数。
活动中的saveSchwein()(因为未找到片段中的函数):
public void saveSchwein(View v) {
Fragment fragment = tabPagerAdapter.getItem(0);
((StammdatenFragment) fragment).saveSchwein();
}
以及片段中的对应功能:
public void saveSchwein() {
if (getActivity() == null) {
System.out.println("getActivity ist null");
}
if (rootView == null) {
System.out.println("rootView ist null");
}
if (isAdded()) { System.out.println("Attached to Activity"); } else { System.out.println("NOT attached to Activity"); }
Schwein schwein = new Schwein();
schwein.setName(add_name.getText().toString());
schwein.setGeschlecht(geschlecht_spinner.getSelectedItem().toString());
schwein.setRasse(rasse_spinner.getSelectedItem().toString());
schwein.setGeburtsdatum(add_geburtsdatum.getText().toString());
schwein.setBesonderheiten(add_besonderheiten.getText().toString());
}
在onCreateView()期间,将rootView和视图分配如下:
rootView = inflater.inflate(R.layout.fragment_schwein_stammdaten, container, false);
add_name = (EditText) rootView.findViewById(R.id.add_name);
geschlecht_spinner = (Spinner) rootView.findViewById(R.id.geschlecht_spinner);
rasse_spinner = (Spinner) rootView.findViewById(R.id.rasse_spinner);
add_geburtsdatum = (TextView) rootView.findViewById(R.id.add_geburtsdatum);
add_besonderheiten = (EditText) rootView.findViewById(R.id.add_besonderheiten);
结果是rootView和getActivity()均为null,而iwego()为false,因此该片段不再附加到该活动。在这一行,我得到了nullpointerexception:
schwein.setName(add_name.getText().toString());
几天以来,我现在一直在寻找问题的答案,但尚未找到正确的答案。但是我通过了解片段的生命周期取得了进步,并发现这与事实有关:在自定义操作栏中,片段在操作期间不处于活动状态。使用Fragment这样的选项菜单时,它可以在Fragment中运行,但是我更喜欢使用自定义操作栏!
有任何想法吗?
您的SchweinFragmentAdapter.getItem函数是什么样的?通常,这些功能只是创建一个片段,而无需先检查该片段是否已存在。这是要检查的第一件事,因为在saveSchwein中,您直接调用getItem,并且要确保您没有创建新的片段(没有视图或活动),然后在该新片段上调用该片段的saveSchwein未配置的片段。那可以解释您所看到的行为。
如果是这种情况,那么您可以改为执行以下操作:
public void saveSchwein(View v) {
Fragment fragment = getSupportFragmentManager().findFragmentByTag("StammdatenFragment");
((StammdatenFragment) fragment).saveSchwein();
}
另一种选择是更改getItem的实现,以便它跟踪已创建的所有片段,并仅在需要时创建新片段。
public static class SchweinFragmentAdapter extends FragmentPagerAdapter {
private Fragment [] fragments = new Fragment[3];
@Override
public Fragment getItem(int position) {
Fragment fragment = fragments[position];
if (fragment == null) {
if (position == 0) {
fragment = new ...
} else if (position == 1) {
fragment = new ...
} else if (position == 2) {
fragment = new ...
}
fragments[position] = fragment;
}
return fragment;
}
}
编辑:
抱歉,我给您的解决方案实际上存在问题。是的,它可以工作,但是也可能导致内存泄漏,因为Android已经在FragmentPagerAdapter中缓存片段。我对此类感到沮丧,因为没有公共API获取适配器将片段添加到您的活动时使用的标签。但是,由于我们可以查看代码,因此可以看到它们在做什么。
更好的解决方案尽管很丑陋,但使用findFragmentByTag。但是,标签不是我最初回答的内容。尝试以下方法:
private static final int POSITION_STAMMDATEN = //TODO the position of your fragment in the adapter
public void saveSchwein(View v) {
Fragment fragment = getSupportFragmentManager().findFragmentByTag(
"android:switcher:" + viewPager.getId() + ":"
+ tabPagerAdapter.getItemId(POSITION_STAMMDATEN)");
((StammdatenFragment) fragment).saveSchwein();
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句