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

标签 java android android-fragments android-lifecycle

问题描述

我正在编写的应用程序有 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/

相关文章:

javascript - 与客户端打印机通讯并打印A4纸

java - 如何拆分 ArrayList 并将数据存储到 android 中的 String 数组中?

Android 进程生命周期详细信息

android - 未找到 ID 为 0x7f0a000e 的 fragment SettingsFragment 的 View

安卓旋转: Why fragment not restored by TAG?

java - 针对 Hibernate 映射定义的 Liquibase diffChangeLog

Java 将 ArrayList 转换为 C#

java - Java 中 ~ 是什么意思?

Android 键盘向下滑动,在屏幕后面留下空白(使用 Fragment)

android - 加载另一个 fragment 时, fragment 数据变为空