问题描述
我正在编写的应用程序有 3 个 fragment 。当我按下搜索按钮时,主 fragment Activity 有一个带有搜索按钮的搜索框,调用以下函数:
Fragments.values()[tabControl.getCurrentItem()].getFragment().search(tv.getText().toString(), MainActivity.this.getApplicationContext());
一切正常,直到我按下 HOME 按钮等待 30 分钟并重新启动应用程序,在我按下 FragmentYellowPages
中的搜索按钮之后 Fragment 应用程序崩溃了
lvYellowPages.setVisibility(View.VISIBLE);
as lvYellowPages
在这种情况下为空,但在日志中我可以看到调用了 onCreateView
函数。你能帮帮我吗,我可以和你分享我的代码。
FragmentPagerAdapter
public class FragmentAdapter extends FragmentPagerAdapter {
Fragments[] mFragments;
public FragmentAdapter(FragmentManager fm) {
super(fm);
mFragments = Fragments.values();
}
public enum Fragments {
Favorites(App.getStringByResId(R.string.favorites), new FragmentFavorites()),
Categories(App.getStringByResId(R.string.categories), new FragmentCategories()),
YellowPages(App.getStringByResId(R.string.yellow_pages), new FragmentYellowPages());
Fragments(String title, BaseListFragment fragment) {
this.mTitle = title;
this.mFragment = fragment;
}
String mTitle;
BaseListFragment mFragment;
public String getTitle() {
return mTitle;
}
public BaseListFragment getFragment() {
return mFragment;
}
};
@Override
public CharSequence getPageTitle(int position) {
return mFragments[position].getTitle();
}
@Override
public Fragment getItem(int position) {
return mFragments[position].getFragment();
}
@Override
public int getCount() {
return mFragments.length;
}
};
列表 fragment
public class FragmentYellowPages extends BaseListFragment {
final static String TAG = FragmentYellowPages.class.getSimpleName();
ListView lvYellowPages;
TextView tvInfo;
SimpleCursorAdapter scAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View yellowPagesView = inflater.inflate(R.layout.fragment_yellow_pages, container, false);
Log.i(TAG, "onCreateView( )");
tvInfo = (TextView) yellowPagesView.findViewById(R.id.tvYellowPagesInfo);
lvYellowPages = (ListView) yellowPagesView.findViewById(android.R.id.list);
return yellowPagesView;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "onCreate( )");
setRetainInstance(true);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.i(TAG, "onActivityCreated( )");
}
@Override
public void onResume() {
super.onResume();
Log.i(TAG, "onResume( )");
}
void updateAdapterOnSearch(final String tts, final String lang) {
Log.i(TAG, String.format("updateAdapterOnSearch(%s, %s)", tts, lang));
/* Show "Yellow Pages" list view and hide Info text view. */
lvYellowPages.setVisibility(View.VISIBLE);
tvInfo.setVisibility(View.GONE);
/* Some code .... */
}
@Override
public void search(final String tts, final Context context) {
Log.i(TAG, String.format("search(%s)", tts));
/* If user search for the text. */
if (tts != null && tts.length() != 0) {
updateAdapterOnSearch(tts, lang);
}
}
};
fragment 布局
<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:background="#ffffc8"
android:tag="FRAGMENT_YELLOW_PAGES_TAG" >
<ListView android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:background="#ffffc8"/>
<TextView android:id="@+id/tvYellowPagesInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="center"
android:padding="5dp"
android:text="@string/no_companies_were_found"
android:visibility="gone"/>
</RelativeLayout>
最佳答案
很难确定确切的问题,但我几乎可以肯定这与您为 ViewPager
构建适配器的方式有关。
Everything works Okay until I press HOME button wait for 30 minutes and relaunch application, after I press Search button in FragmentYellowPages Fragment application crashes
由于 Activity
在后台(并且显然已被杀死),它会在返回前台时重新创建其内容。此时 ViewPager
将重建其内容,但其适配器不会调用 getItem()
,因为它拥有自行重建先前 fragment 的所有数据。所以你最终会得到两个 fragment 版本,一个当前在 ViewPager
中可见(所以你看到 onCreateView()
被调用)和那些在 枚举
。 enum
中的那些 fragment 未绑定(bind)到 Activity
,因此不会为它们运行整个回调堆栈,因此 onCreateView()
不会被调用,这将使您的 lvYellowPages ListView
null
。
顺便说一句,这是我第一次看到在 enum
中构建适配器的 fragment ,我建议您避免这种情况。
解决办法就是不要在外面引用ViewPager
的 fragment 。使 getItem()
方法返回一个 Fragment
实例,如果您需要访问这些 fragment ,有一些方法可以在不存储 ViewPager
的情况下执行此操作列表/枚举等中的 s fragment (在 stackoverflow 上快速搜索应该会向您显示有关此的问题):
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new FragmentFavorites();
case 1:
return new FragmentCategories();
case 2:
return new FragmentYellowPages();
}
return null;
}
@Override
public int getCount() {
return 3;
}
还有:
setRetainInstance(true);
我不会用这个。保留 ViewPager
使用的 fragment 没有意义(因为我不认为你打算将它移动到其他地方)并且它也不会保护你免受被杀死的 Activity 在后台。
关于java - 按下主页按钮并等待后, fragment 中的类成员变为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17161159/