在片段类成员成为仅次于Home键preSS零等待 [英] Class members in Fragment become null after Home button press and wait
问题描述
问题说明
应用程序,我写了3个片段。主要片段活动有一个搜索框搜索按钮时,I $上的搜索按钮下方的功能被称为P $ PSS:
<$p$p><$c$c>Fragments.values()[tabControl.getCurrentItem()].getFragment().search(tv.getText().toString(), MainActivity.this.getApplicationContext());
一切正常,好吧,直到我preSS HOME键等待30分钟,然后重新启动应用程序,之后我美元的对 FragmentYellowPages
片段应用程序崩溃p $ PSS搜索按钮行
lvYellowPages.setVisibility(View.VISIBLE);
为 lvYellowPages
在这种情况下是空的,但在日志中我可以看到 onCreateView
函数被调用。能否请你帮我,我可以与大家分享我的code。
FragmentPagerAdapter
公共类FragmentAdapter扩展FragmentPagerAdapter {
片段[] mFragments;
公共FragmentAdapter(FragmentManager FM){
超(FM);
mFragments = Fragments.values();
}
公共枚举片段{
收藏夹(App.getStringByResId(R.string.favorites),新FragmentFavorites()),
分类(App.getStringByResId(R.string.categories),新FragmentCategories()),
黄页(App.getStringByResId(R.string.yellow_pages),新FragmentYellowPages());
片段(字符串名称,BaseListFragment片段){
this.mTitle =称号;
this.mFragment =片段;
}
字符串mTitle;
BaseListFragment mFragment;
公共字符串的getTitle(){
返回mTitle;
}
公共BaseListFragment getFragment(){
返回mFragment;
}
};
@覆盖
公共CharSequence的getPageTitle(INT位置){
返回mFragments [位置] .getTitle();
}
@覆盖
公共片段的getItem(INT位置){
返回mFragments [位置] .getFragment();
}
@覆盖
公众诠释getCount将(){
返回mFragments.length;
}
};
列表片段
公共类FragmentYellowPages扩展BaseListFragment {
最终静态字符串变量= FragmentYellowPages.class.getSimpleName();
ListView控件lvYellowPages;
TextView的tvInfo;
SimpleCursorAdapter scAdapter;
@覆盖
公共查看onCreateView(LayoutInflater充气,容器的ViewGroup,捆绑savedInstanceState){
查看yellowPagesView = inflater.inflate(R.layout.fragment_yellow_pages,集装箱,假);
Log.i(TAG,onCreateView());
tvInfo =(TextView中)yellowPagesView.findViewById(R.id.tvYellowPagesInfo);
lvYellowPages =(ListView控件)yellowPagesView.findViewById(android.R.id.list);
返回yellowPagesView;
}
@覆盖
公共无效的onCreate(包savedInstanceState){
super.onCreate(savedInstanceState);
Log.i(TAG的onCreate());
setRetainInstance(真正的);
}
@覆盖
公共无效onActivityCreated(包savedInstanceState){
super.onActivityCreated(savedInstanceState);
Log.i(TAG,onActivityCreated());
}
@覆盖
公共无效onResume(){
super.onResume();
Log.i(TAG,onResume());
}
无效updateAdapterOnSearch(最后弦乐TTS,最后弦乐朗){
Log.i(TAG,的String.Format(updateAdapterOnSearch(%S,%S),TTS,郎));
/ *显示黄页列表视图和隐藏信息的文本视图。 * /
lvYellowPages.setVisibility(View.VISIBLE);
tvInfo.setVisibility(View.GONE);
/ *一些code .... * /
}
@覆盖
公共无效搜索(最后弦乐TTS,最终上下文语境){
Log.i(TAG,的String.Format(搜索(%S),TTS));
/ *如果用户搜索的文本。 * /
如果(TTS =空&安培;!&安培;!tts.length()= 0){
updateAdapterOnSearch(TTS,郎);
}
}
};
片段布局
&LT; RelativeLayout的的xmlns:机器人=http://schemas.android.com/apk/res/android
的xmlns:工具=http://schemas.android.com/tools
机器人:layout_width =match_parent
机器人:layout_height =match_parent
机器人:后台=#ffffc8
机器人:标签=FRAGMENT_YELLOW_PAGES_TAG&GT;
&LT; ListView的机器人:ID =@机器人:ID /列表
机器人:layout_width =match_parent
机器人:layout_height =WRAP_CONTENT
机器人:能见度=水涨船高
机器人:后台=#ffffc8/&GT;
&LT; TextView的机器人:ID =@ + ID / tvYellowPagesInfo
机器人:layout_width =WRAP_CONTENT
机器人:layout_height =WRAP_CONTENT
机器人:layout_centerHorizontal =真
机器人:layout_centerVertical =真
机器人:重力=中心
机器人:填充=5DP
机器人:文本=@字符串/ no_companies_were_found
机器人:能见度=水涨船高/&GT;
&LT; / RelativeLayout的&GT;
这是很难找出确切的问题,但我几乎可以肯定它与你建立适配器的方式 ViewPager
。
一切正常,好吧,直到我preSS HOME键等待30分钟 并重新启动应用程序,之后我preSS搜索的按钮 FragmentYellowPages片段应用程序崩溃
由于活动
在后台(显然杀死)正在添加回到前台时,它会创建其内容。此时 ViewPager
将重建其内容,但它的适配器不会叫的getItem()
,因为它拥有所有的数据重新创建previous片段就可以拥有。所以,你最终有两个版本的片段,那些目前在 ViewPager
(让你看到的 onCreateView()$ C $可见C>被调用)和那些在
枚举
。从这些片段枚举
不依赖于活动
等整个回调栈不是为他们跑,所以 onCreateView()
将不会被调用,这将使你的 lvYellowPages 的的ListView
空
。
顺便说一句,这是我第一次看到一个适配器的片段被建在一个枚举
,我建议你避免这种情况。
解决方案是不引用的 ViewPager
之外的片段。使的getItem()
方法返回一个片段
例如,如果你需要访问这些片段有办法做到这一点不存储 ViewPager
的片段列表/枚举等(计算器上快速搜索会显示出这个问题):
@覆盖
公共片段的getItem(INT位置){
开关(位置){
情况下0:
返回新FragmentFavorites();
情况1:
返回新FragmentCategories();
案例2:
返回新FragmentYellowPages();
}
返回null;
}
@覆盖
公众诠释getCount将(){
返回3;
}
另外:
setRetainInstance(真正的);
我不会用这个。这是没有意义的保留使用的片段 ViewPager
(因为我不认为你刨去移动它在其他地方),也将不保您从活动被杀害的背景。
Problem Description
Application which I'm writing has 3 Fragments. Main Fragment Activity has a Search Box with Search button when I press on a Search button the function below is called:
Fragments.values()[tabControl.getCurrentItem()].getFragment().search(tv.getText().toString(), MainActivity.this.getApplicationContext());
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 on the lines
lvYellowPages.setVisibility(View.VISIBLE);
as lvYellowPages
in this case is null, but In a logs I can see that onCreateView
function is called. Can you please help me, I can share my code with you.
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;
}
};
List 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 Layout
<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>
It's hard to pinpoint the exact problem but I'm almost sure it has to do with the way you built the adapter for the 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
As the Activity
is in the background(and apparently killed) it will recreate its content when comming back to the foreground. At this point the ViewPager
will rebuild its content, but its adapter will not call getItem()
as it has all the data to recreate the previous fragments on it own. So you'll end up with two fragment version, the ones currently visible in the ViewPager
(so you see the onCreateView()
being called) and those that are in the enum
. Those fragments from the enum
aren't tied to the Activity
and so the entire callbacks stack isn't run for them, so onCreateView()
will not be called, which will make your lvYellowPages ListView
null
.
Btw, this is the first time I've seen the fragments of an adapter being built in a enum
and I recommend that you avoid this.
The solution is to not reference the fragments of the ViewPager
outside. Make the getItem()
method return a Fragment
instance and if you need to access those fragment there are ways to do it without storing the ViewPager
's fragment in lists/enums etc(a quick search on stackoverflow should show you a question about this):
@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;
}
Also:
setRetainInstance(true);
I wouldn't use this. It doesn't make sense to retain a fragment used by a ViewPager
(as I don't think you're planing to move it somewhere else) and it will also not protect you from the activity being killed in the background.
这篇关于在片段类成员成为仅次于Home键preSS零等待的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!