主页按钮按下并等待后,Fragment中的类成员变为空

Vik*_*yan 7 java android android-lifecycle android-fragments

问题描述

我写的应用程序有3个片段.当我按下搜索按钮时,主片段活动有一个带搜索按钮的搜索框,调用下面的函数:

Fragments.values()[tabControl.getCurrentItem()].getFragment().search(tv.getText().toString(), MainActivity.this.getApplicationContext());
Run Code Online (Sandbox Code Playgroud)

一切正常,直到我按下HOME按钮等待30分钟并重新启动应用程序,在我按下FragmentYellowPagesFragment应用程序中的搜索按钮后崩溃

lvYellowPages.setVisibility(View.VISIBLE);
Run Code Online (Sandbox Code Playgroud)

因为lvYellowPages在这种情况下是null,但在日志中我可以看到该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;
    }
};
Run Code Online (Sandbox Code Playgroud)

列表片段

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

};
Run Code Online (Sandbox Code Playgroud)

片段布局

<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>
Run Code Online (Sandbox Code Playgroud)

Luk*_*rog 8

很难确定确切的问题,但我几乎可以肯定它与你为它构建适配器的方式有关ViewPager.

一切正常,直到我按下HOME按钮等待30分钟并重新启动应用程序,在FragmentYellowPages Fragment应用程序崩溃后按下搜索按钮

由于Activity它在后台(并且显然被杀死),它将在返回前景时重新创建其内容.此时,ViewPager将重建其内容,但其适配器将不会调用,getItem()因为它具有所有数据以自己重新创建先前的片段.因此,您最终会得到两个片段版本,即当前可见的片段ViewPager(因此您可以看到onCreateView()被调用者)和那些片段版本enum.来自它的那些片段enum并没有绑定Activity,因此整个回调栈不会为它们运行,所以onCreateView()不会被调用,这将使你的lvYellowPages ListView null.

顺便说一下,这是我第一次看到适配器的片段是在一个内置的enum,我建议你避免这种情况.

解决方案是不参考ViewPager外部的碎片.制作getItem()方法返回一个Fragment实例,如果你需要访问那些片段,有办法不用将ViewPager列表存储在列表/枚举等中(快速搜索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;
}
Run Code Online (Sandbox Code Playgroud)

也:

setRetainInstance(true);
Run Code Online (Sandbox Code Playgroud)

我不会用这个.保留a使用的片段是没有意义的ViewPager(因为我不认为你正在计划将其移动到其他地方)并且它也不会保护你免受在后台被杀死的活动.