使用从滑动选项卡的片段适配器调用的ListFragment时,应用程序在退出时崩溃

时间:2013-05-28 15:42:26

标签: android-listview android-fragments

我花了将近两天的时间试图弄清楚为什么会这样,但到目前为止找不到解决办法。所以我在这里发帖。

我有一个非常通用的Sliding Tab,它是在Eclipse中为较新的Android API创建的。在其中一个滑动标签中,我调用了ListFragment。此ListFragment使用CursorLoader加载一些数据。

现在当应用程序退出时,它会给出:05-28 11:34:00.327:E / AndroidRuntime(31994):java.lang.RuntimeException:无法销毁活动{com.example.myapp / com.example.myapp .main.HomeActivity}:java.lang.NullPointerException

我尝试过使用ChildFragmentManager以及最新的支持包,但无济于事。

这是调用另一个片段的唯一选项卡,否则只调用静态XML内容的其他选项卡工作正常。如果我删除此选项卡,应用程序工作正常。

据我所知,我需要销毁CursorLoader或以某种方式在应用程序退出之前分离这个特定的片段。 CursorLoader似乎被破坏,并且HomeActivty中捕获了错误。也许我应该在HomeActivity中调用onDestroy,但实际上并不确切知道如何以及在何处。

调用HomeActivity的代码非常标准:

ViewPager mViewPager;
private static final String DEBUG_TAG = "MY APP"; 

private static boolean logged_in;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home);

    sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
    logged_in = sharedPrefs.getBoolean("logged_in", false);

    Log.v(DEBUG_TAG, "logged_in: " + logged_in);

    mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

    mViewPager = (ViewPager) findViewById(R.id.pager);
    mViewPager.setAdapter(mSectionsPagerAdapter);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.home, menu);
    return true;
}


public class SectionsPagerAdapter extends FragmentPagerAdapter {

    public SectionsPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment;

        switch(position) {
        case 0:
              fragment = new MySectionFragment();
            break;
        case 1:
                ...

从FragmentActivity调用ListFragment的代码如下:

public static class MySectionFragment extends Fragment {
    public MySectionFragment() {}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_my_section, container, false);
    }

    public void onDestroyView() {
        super.onDestroyView(); 
        Fragment fragment = (getFragmentManager().findFragmentById(R.id.fragment_my_section));

        if (fragment != null) {
            FragmentTransaction ft = getFragmentManager().beginTransaction();
            ft.remove(fragment);
            ft.commitAllowingStateLoss();   
        }
    }
}

1 个答案:

答案 0 :(得分:0)

最后我找到了答案,它是代码中最意想不到的地方。我仍然不理解这些机制,但我已经确认它是有效的。

我正在使用Android 4.0.3和支持库rev 12。

原来我的代码非常好,我甚至不需要onDestroyView()。视图被破坏并重新生成。无需处理FragmentManager,SupportFragmentManager或ChildSupportFragmentManager。选择可跳转选项卡时在Eclipse中生成的默认代码就可以了。

我做出更改的唯一地方就是XML模板。我将android:id从'fragment'部分移动到'RelativeLayout'部分。

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout
    android:id="@+id/fragment_my_section"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:paddingTop="4dp"
    android:background="@drawable/bg"> 

<ListView
    android:id="@android:id/list"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:drawSelectorOnTop="false"
    android:cacheColorHint="#00000000"/>

<fragment
    android:name="com.example.MyFragmentActivity"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
</fragment>

</RelativeLayout>

以前,id位于“片段”部分。这是在XML文件中没有定义RelativeLayout和ListView的时候。

毋庸置疑,我讨厌这个Android开发世界中的XML。大多数时候它一直是一个浪费我的时间的XML文件,没有例外。 IDE也不能很好地捕获这些XML问题。我希望Android开发完全摆脱或完全放弃XML。