使用viewPager时无法恢复活动

时间:2013-08-26 12:37:26

标签: java android android-fragments android-viewpager illegalstateexception

我一直在使用viewPager遇到问题,我试图添加到我的应用中。

我有一个SearchResultActivity,里面有一个抽屉。具有以下布局:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<FrameLayout
    android:id="@+id/content_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

<ListView
    android:id="@+id/left_drawer"
    android:layout_width="240dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:background="#111"
    android:choiceMode="singleChoice"
    android:divider="@android:color/transparent"
    android:dividerHeight="0dp" />

因为我使用片段,在第一次到达此活动时,我打开使用事务在Activity的onCreate方法中打开RecipeHeadlinesFragment:

    @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.drawer_main);
    mSearchType = getIntent().getIntExtra(SEARCH_TYPE, -1);
    if (mSearchType == ICON_SEARCH) {
        mVeggieNamesIcons = getIntent().getStringArrayListExtra(
                VEGGIE_NAME_ARR);
        mVeggieUrlsIcons = getIntent().getStringArrayListExtra(
                VEGGIE_URLS_ARR);
    } else if (mSearchType == QUERY_SEARCH) {
        mQuery = getIntent().getStringExtra(QUERY);
    }
    // Generate title
    title = new String[] { "Search for a recipe", "My profile",
            "Title Fragment 3" };

    // Generate subtitle
    subtitle = new String[] { "", "", "Subtitle Fragment 3" };

    // Generate icon
    icon = new int[] { R.drawable.action_about, R.drawable.action_settings,
            R.drawable.collections_cloud };

    // Locate DrawerLayout in drawer_main.xml
    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);

    // Locate ListView in drawer_main.xml
    mDrawerList = (ListView) findViewById(R.id.left_drawer);

    // Set a custom shadow that overlays the main content when the drawer
    // opens
    mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow,
            GravityCompat.START);

    // Pass results to MenuListAdapter Class
    mMenuAdapter = new MenuListAdapter(this, title, subtitle, icon);

    // Set the MenuListAdapter to the ListView
    mDrawerList.setAdapter(mMenuAdapter);

    // Capture button clicks on side menu
    mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

    // Enable ActionBar app icon to behave as action to toggle nav drawer
    getSupportActionBar().setHomeButtonEnabled(true);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    // ActionBarDrawerToggle ties together the the proper interactions
    // between the sliding drawer and the action bar app icon
    mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
            R.drawable.menubutton, R.string.drawer_open,
            R.string.drawer_close) {

        public void onDrawerClosed(View view) {
            getActionBar().setTitle("");
            // getActionBar().setBackgroundDrawable(d)
            super.onDrawerClosed(view);
            invalidateOptionsMenu();
        }

        public void onDrawerOpened(View drawerView) {
            getActionBar().setTitle("menu");
            // getActionBar().setBackgroundDrawable(new
            // ColorDrawable(Color.GREEN));
            super.onDrawerOpened(drawerView);
            invalidateOptionsMenu();
        }
    };

    mDrawerLayout.setDrawerListener(mDrawerToggle);
    // Check whether the activity is using the layout version with
    // the fragment_container FrameLayout. If so, we must add the first
    // fragment
    if (findViewById(R.id.content_frame) != null) {
        if (savedInstanceState == null) {
            Bundle args = new Bundle();
            args.putInt(SEARCH_TYPE, mSearchType);
            if (mSearchType == QUERY_SEARCH) {
                args.putString(QUERY, mQuery);
            } else if (mSearchType == ICON_SEARCH) {
                args.putStringArrayList(VEGGIE_NAME_ARR, mVeggieNamesIcons);
                args.putStringArrayList(VEGGIE_URLS_ARR, mVeggieUrlsIcons);
            }

            recipeHeadlines.setArguments(args);
            // Add the fragment to the 'fragment_container' FrameLayout
            FragmentTransaction ft = getSupportFragmentManager()
                    .beginTransaction().replace(R.id.content_frame,
                            recipeHeadlines);
            ft.commit();
        } else {
            return;
        }
    }

    getActionBar().setIcon(R.color.transparent);
}

RecipeHeadlinesFragment是一个sherlockListFragment。我在其中创建了一个onArticleSelectedListener接口,并使活动实现它,这样当选择列表项时,将调用活动的onArticleSelected方法并启动RecipeTabsFragment并使用另一个传递给前端事务:

    public void onArticleSelected(int position, RecipeObj obj) {
    // The user selected the headline of an article from the
    // HeadlinesFragment

    // Capture the article fragment from the activity layout
    RecipeTabsFragment articleFrag = (RecipeTabsFragment) getSupportFragmentManager()
            .findFragmentById(R.id.pager);

    if (articleFrag != null) {
        // If article frag is available, we're in two-pane layout...

        // Call a method in the ArticleFragment to update its content
        articleFrag.updateArticleView(position, obj);
        // todo update data

    } else {
        // If the frag is not available, we're in the one-pane layout and
        // must swap frags...

        // Create fragment and give it an argument for the selected article
        RecipeTabsFragment newFragment = new RecipeTabsFragment();
        Bundle args = new Bundle();
        args.putParcelable(RecipeTabsFragment.ARG_RECIPE, obj);
        args.putInt(RecipeTabsFragment.ARG_POSITION, position);
        newFragment.setArguments(args);
        FragmentTransaction transaction = getSupportFragmentManager()
                .beginTransaction();

        // Replace whatever is in the fragment_container view with this
        // fragment,
        // and add the transaction to the back stack so the user can
        // navigate back
        transaction.replace(R.id.content_frame, newFragment);


        // Commit the transaction
        transaction.commit();
    }
}

这是我的RecipeTabsFragment代码:

public class RecipeTabsFragment extends SherlockFragment {
// Declare Variables
final static String ARG_POSITION = "position";
final static String TAB_POSITION = "tab";
final static String ARG_RECIPE = "recipeData";

View rootView;
ActionBar mActionBar;
TextView mRecipeTitle;
TextView mRecipeBloger;
RatingBar mRecipeRatingBar;

int mCurrentPosition = -1;
int mCurrentTab = 0;

static ViewPager mPager;
Tab tab;
FragmentStatePagerAdapter mAdapter;
static final int NUM_ITEMS = 3;
// View rootView;
EditText editsearch;

ProgressDialog mProgressDialog;
// ImageAndName[] mTemplist = {};
GridView gridview;

private RecipeObj mRecipeData;
// The container Activity must implement this interface so the frag can
// deliver messages
public interface OnNameSetter {
    /** Called by HeadlinesFragment when a list item is selected */
    public void setName(String name);
    public String getName();
}


public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

}

@Override
public void onPrepareOptionsMenu(Menu menu) {
    //initialize the recipe title,bloger and rating view on the action bar
    MenuItem item = menu.findItem(R.id.data_item);

    mRecipeTitle = (TextView) item.getActionView().findViewById(
            R.id.tv_title_ab);
    mRecipeBloger = (TextView) item.getActionView().findViewById(
            R.id.tv_bloger_ab);
    mRecipeRatingBar = (RatingBar) item.getActionView().findViewById(
            R.id.rb_list_item_ab);

    //set the actual data to the view
     mRecipeTitle.setText(mRecipeData.getFields().getName());
    super.onPrepareOptionsMenu(menu);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.recip_detail, menu);
    super.onCreateOptionsMenu(menu, inflater);
}

@SuppressWarnings("null")
@Override
public void onStart() {
    super.onStart();
    Bundle args = getArguments();
    if (args != null) {
        // Set article based on argument passed in
        updateArticleView(args.getInt(ARG_POSITION), (RecipeObj) args.getParcelable(ARG_RECIPE));



    } else if (mCurrentPosition != -1) {
        // Set article based on saved instance state defined during
        // onCreateView

        updateArticleView(mCurrentPosition, mRecipeData);
    }
}

public void updateArticleView(int position, RecipeObj data) {

    mRecipeData = data;
    mCurrentPosition = position;
}

public void onResume() {
    super.onResume();
    //allows to put data on action bar that is not a action widget
    getSherlockActivity().supportInvalidateOptionsMenu();
    mActionBar = getSherlockActivity().getSupportActionBar();
    mActionBar.setTitle("");

    FragmentManager fm = getSherlockActivity().getSupportFragmentManager();
    final ArrayList<String> titles = new ArrayList<String>();
    titles.add("tab1");
    titles.add("tab2");
    titles.add("tab3");
    mAdapter = new FragmentStatePagerAdapter(fm){

        @Override
        public Fragment getItem(int position) {
            switch (position) {
            case 0:
                // Your current main fragment showing how to send arguments to
                // fragment
                RecipeArticle fragment1 = new RecipeArticle();
                Bundle data1 = new Bundle();
                data1.putParcelable(RecipeTabsFragment.ARG_RECIPE, mRecipeData);
                fragment1.setArguments(data1);
                  fragment1.setName(titles.get(position));
                return fragment1;
            case 1:
                // Calling a Fragment without sending arguments
                RecipePreparation fragment2 = new RecipePreparation();
                Bundle data2 = new Bundle();
                data2.putParcelable(RecipeTabsFragment.ARG_RECIPE, mRecipeData);
                fragment2.setArguments(data2);
                 fragment2.setName(titles.get(position));
                return fragment2;
            case 2:
                Fragments3 fragment3 = new Fragments3();
                // Bundle data2 = new Bundle();
                // data2.putParcelable(IngrFragment.ARG_RECIPE, recipeData);
                // fragment2.setArguments(data2);
                 fragment3.setName(titles.get(position));

                return fragment3;
            default:
                return null;
            }
        }

        @Override
        public int getCount() {
            // TODO Auto-generated method stub
            return NUM_ITEMS;
        }
        @Override
         public int getItemPosition(Object item) {
                OnNameSetter fragment = (OnNameSetter)item;
                String title = fragment.getName();
                int position = titles.indexOf(title);

                if (position >= 0) {
                    return position;
                } else {
                    return POSITION_NONE;
                }
            }

    };
    mPager = (ViewPager) rootView.findViewById(R.id.pager);
    mPager.setAdapter(mAdapter);
    mAdapter.notifyDataSetChanged();
    mPager.setOnPageChangeListener(new OnPageChangeListener() {

        @Override
        public void onPageScrollStateChanged(int arg0) {

        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {

        }

        //
        // @Override
        public void onPageSelected(int arg0) {

            mActionBar.getTabAt(arg0).select();
        }

    });

    mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    // Create first Tab
    tab = mActionBar
            .newTab()
            .setText(getString(string.ingrdients))
            .setTabListener(
                    new TabListener<RecipeArticle>(this
                            .getSherlockActivity(), "SearchPage1",
                            RecipeArticle.class));
    tab.setIcon(R.drawable.ing);
    mActionBar.addTab(tab);

    // Create second Tab
    tab = mActionBar
            .newTab()
            .setText(getString(string.prepration))
            .setTabListener(
                    new TabListener<RecipePreparation>(this
                            .getSherlockActivity(), "SearchPage2",
                            RecipePreparation.class));
    tab.setIcon(R.drawable.how);
    mActionBar.addTab(tab);

    // Create third Tab
    tab = mActionBar
            .newTab()
            .setText(getString(string.comments))
            .setTabListener(
                    new TabListener<Fragments3>(this.getSherlockActivity(),
                            "SearchPage3", Fragments3.class));
    tab.setIcon(R.drawable.why);
    mActionBar.addTab(tab);
    setHasOptionsMenu(true);
    mActionBar.getTabAt(mCurrentTab).select();

}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    if (savedInstanceState != null) {
        mCurrentPosition = savedInstanceState.getInt(ARG_POSITION);
        mRecipeData = savedInstanceState.getParcelable(ARG_RECIPE);
        mCurrentTab = savedInstanceState.getInt(TAB_POSITION);

    }
    rootView = inflater.inflate(R.layout.ingr_tabs, container, false);


    return rootView;
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    // Save the current article selection in case we need to recreate the
    // fragment
    outState.putInt(ARG_POSITION, mCurrentPosition);
    outState.putInt(TAB_POSITION, mCurrentTab);
    outState.putParcelable(ARG_RECIPE, mRecipeData);
}


public static class TabListener<T extends Fragment> implements
        ActionBar.TabListener {
    private Fragment mFragment;
    private final SherlockFragmentActivity mActivity;
    private final String mTag;
    private final Class<T> mClass;

    /**
     * Constructor used each time a new tab is created.
     * 
     * @param sherlockFragmentActivity
     *            The host Activity, used to instantiate the fragment
     * @param tag
     *            The identifier tag for the fragment
     * @param clz
     *            The fragment's Class, used to instantiate the fragment
     */
    public TabListener(SherlockFragmentActivity sherlockFragmentActivity,
            String tag, Class<T> clz) {
        mActivity = sherlockFragmentActivity;
        mTag = tag;
        mClass = clz;
    }

    /* The following are each of the ActionBar.TabListener callbacks */

    public void onTabSelected(Tab tab, FragmentTransaction ft) {

        mPager.setCurrentItem(tab.getPosition());

    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {
        // User selected the already selected tab. Usually do nothing.
    }
}

}

这是RecipeTabsFragment布局,ingr_tabs.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:tag="ingr_screen"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<android.support.v4.view.ViewPager
    android:id="@+id/pager"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >
</android.support.v4.view.ViewPager>

现在,出于某种原因,在RecipeTabsFragment中,暂时离开应用程序(无论是退出主菜单,还是设备进入睡眠模式)并返回应用程序,应用程序崩溃并发生以下异常:

## 08-26 14:39:30.640: E/AndroidRuntime(5520): FATAL EXCEPTION: main
08-26 14:39:30.640: E/AndroidRuntime(5520): java.lang.RuntimeException: Unable to resume activity {development.example.vegancookbook/development.example.vegancookbook.SearchResultActivity}: java.lang.IllegalStateException: Observer android.support.v4.view.ViewPager$PagerObserver@414db9b0 was not registered.
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2456)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2484)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1185)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.os.Handler.dispatchMessage(Handler.java:99)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.os.Looper.loop(Looper.java:137)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.app.ActivityThread.main(ActivityThread.java:4507)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at java.lang.reflect.Method.invokeNative(Native Method)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at java.lang.reflect.Method.invoke(Method.java:511)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at dalvik.system.NativeStart.main(Native Method)
08-26 14:39:30.640: E/AndroidRuntime(5520): Caused by: java.lang.IllegalStateException: Observer android.support.v4.view.ViewPager$PagerObserver@414db9b0 was not registered.
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.database.Observable.unregisterObserver(Observable.java:64)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.support.v4.view.PagerAdapter.unregisterDataSetObserver(PagerAdapter.java:294)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.support.v4.view.ViewPager.setAdapter(ViewPager.java:409)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at development.example.vegancookbook.RecipeTabsFragment.onResume(RecipeTabsFragment.java:196)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.support.v4.app.Fragment.performResume(Fragment.java:1521)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:963)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1460)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:472)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.support.v4.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:163)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.support.v4.view.ViewPager.setAdapter(ViewPager.java:415)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at development.example.vegancookbook.RecipeTabsFragment.onResume(RecipeTabsFragment.java:196)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.support.v4.app.Fragment.performResume(Fragment.java:1521)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:963)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1086)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.support.v4.app.FragmentManagerImpl.dispatchResume(FragmentManager.java:1887)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.support.v4.app.FragmentActivity.onResumeFragments(FragmentActivity.java:460)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.support.v4.app.FragmentActivity.onPostResume(FragmentActivity.java:449)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at com.actionbarsherlock.app.SherlockFragmentActivity.onPostResume(SherlockFragmentActivity.java:69)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.app.Activity.performResume(Activity.java:4552)
08-26 14:39:30.640: E/AndroidRuntime(5520):     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2446)
08-26 14:39:30.640: E/AndroidRuntime(5520):     ... 10 more
 ##

有没有人知道什么是错的? 发生并且可能相关的另一件事是,当我在RecipeTabsFragment中,并按下后退按钮时,我会回到我的应用程序的主要活动,而不是RecipeHeadlinesFragment,尽管这是我的实际位置#39;去过RecipeTabsFragment之前。 帮助任何人? 的修改: 所以我想我找到了我要问的主要问题的原因...... 当我在我的fragement中时,我调用getSherlockActivity()来获取FragmentManager而不是调用片段的getChildFragmentManager()。 问题解决了。

2 个答案:

答案 0 :(得分:10)

我发现了问题所在,我最好为后代回答我的问题...... 我在片段中使用了getSupportFragmentManager()而不是使用getChildFragmentManager()。 就是这样。

答案 1 :(得分:0)

这是因为当尝试释放已经释放的观察者时,Observable类会抛出异常。

你可以覆盖unregisterDataSetObserver类中的FragmentStatePagerAdapter,如果给定的观察者为空,则不要调用super。

这样的事情: -

@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
  if (observer != null) {
    super.unregisterDataSetObserver(observer);
  }
} 

希望这有帮助。