包含ViewPager的Activity上的IllegalStateException使用FragmentStatePagerAdapter重新启动actvity

时间:2015-08-04 05:18:45

标签: android android-activity android-viewpager illegalstateexception

我有一个由ViewPager组成的Activity。

此ViewPager显示由Grid of Tiles组成的Fragment。由于要显示的片段数量未知,我使用的是FragmentStatePagerAdapter。

问题是这样的:

首次启动时,会正常创建活动,并且所有必需的碎片都会在viewpager中正确显示。

但是当我关闭活动并尝试再次启动它时,我得到了 以下错误:

  

引起:java.lang.IllegalStateException:Fragment EventGridFragment {162f70f8}当前不在FragmentManager中               在android.app.FragmentManagerImpl.saveFragmentInstanceState(FragmentManager.java:595)

然后应用程序崩溃了。 当我再次启动它时,应用程序正常启动并重复上述循环。

我在博客文章,自我分析和Stack-Overflow中的调查结果表明:

  

FragmentStatePAgerAdapter中存在错误。

     

我需要从头开始启动活动/使用启动模式的一些标志

如果有人有这方面的解决方案,请帮助我。 请记住我是这个领域的新手:) 以下是活动代码:

//Lighter Home View and heavy lifting done by presenters
public class HomeActivity extends AppCompatActivity implements HomeView, View.OnClickListener, PlayServicesView {

    private static final String TAG = "Home Activity";
    private static final String MYEVENTSTAG = "MY";
    private static final String TOPEVENTS = "TOP";
    private static final String FEATUREDEVENTS = "FEATURED";
    private static final String LATESTEVENTS = "LATEST";
    private static final String LOCALEVENTS = "LOCAL";
    private HomeAdapter mHomeAdapter;
    private HomePresenter mHomePresenter;
    private static final int REQUEST_ACHIEVEMENTS = 1001;
    private static final int REQUEST_LEADERBOARD = 1002;
    @InjectView(R.id.activity_home_toolbar)
    Toolbar mToolbar;
    @InjectView(R.id.activity_events_progress)
    ProgressBar mProgressBar;
    @InjectView(R.id.activity_home_viewPager)
    ViewPager mViewPager;
    @InjectView(R.id.pager_header)
    PagerSlidingTabStrip mPagerTabStrip;
    @InjectView(R.id.drawer_layout)
    DrawerLayout mDrawerLayout;
    private User mUser;

    private PlayServicesPresenter mPlayServicesPresenter;
    @InjectView(R.id.imgUserCover)
    ImageView mImgUserCover;
    @InjectView(R.id.imgUserProfile)
    ImageView mImgUserProfilePic;
    @InjectView(R.id.txtUserName)
    TextView mTxtUserName;
    @InjectView(R.id.txtUserEmail)
    TextView mTextUserEmail;
    @InjectView(R.id.navigation_view)
    NavigationView mNavigationView;
    GoogleApiClient mGoogleApiClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        ButterKnife.inject(this);
        setSupportActionBar(mToolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);
        getSupportActionBar().setIcon(R.mipmap.ic_launcher);
        getSupportActionBar().setHomeAsUpIndicator(
                R.drawable.ic_menu_white_24dp);

        mPlayServicesPresenter = new PlayServicesPresenter(this, true);
        mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mDrawerLayout.openDrawer(GravityCompat.START);
            }
        });

        if (savedInstanceState == null) {
            mHomePresenter = new HomePresenter(this);
        } else {
            EventCategoriesWrapper eventCategoriesWrapper = (EventCategoriesWrapper) savedInstanceState
                    .getSerializable("event_categories_wrapper");
            mHomePresenter = new HomePresenter(this, eventCategoriesWrapper);
        }

    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void onActivityReenter(int resultCode, Intent data) {

        super.onActivityReenter(resultCode, data);
        Log.d("[DEBUG]", "Home Activity onActivityReenter - Re-enter");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_home, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        switch (id) {
            case R.id.action_settings:

                this.startActivity(new Intent(HomeActivity.this, AppSettings.class));
                break;
            case R.id.action_socialLogin:

                this.startActivity(new Intent(HomeActivity.this, SocialLoginActivity.class));
                break;
            case R.id.action_signout:
                if(mGoogleApiClient!=null){
                    if (mGoogleApiClient.isConnected()) {
                        Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
                        mGoogleApiClient.disconnect();
                        startActivity(new Intent(HomeActivity.this,Splash.class));
                        finish();
                    }
                }
                break;
        }
        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            Intent i = new Intent(HomeActivity.this, AppSettings.class);
            this.startActivity(i);

        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onResume() {
        super.onResume();

        // Logs 'install' and 'app activate' App Events.
        AppEventsLogger.activateApp(this);
    }

    @Override
    protected void onStart() {
        super.onStart();
        mPlayServicesPresenter.start();

    }

    @Override
    protected void onStop() {
        super.onStop();
        //Call for login

        mHomePresenter.stop();
    }


    @Override
    protected void onSaveInstanceState(Bundle outState) {

        super.onSaveInstanceState(outState);

        if (mHomeAdapter != null) {

            outState.putSerializable("event_categories_wrapper",
                    new EventCategoriesWrapper(mHomeAdapter.getEventCategoriesList()));

        }

    }

    @Override
    public void showEventCategories(List<EventCategory> eventCategoryList) {

        mHomeAdapter = new HomeAdapter(getFragmentManager(), eventCategoryList);
        mHomeAdapter.notifyDataSetChanged();

        mViewPager.setAdapter(mHomeAdapter);
        mPagerTabStrip.setViewPager(mViewPager);
        mPagerTabStrip.setIndicatorColor(Color.parseColor(eventCategoryList.get(0).getCatColor()));
        mPagerTabStrip.setTextColor(Color.BLACK);
        mPagerTabStrip.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int i, float v, int i1) {

            }

            @Override
            public void onPageSelected(int i) {

                mPagerTabStrip.setIndicatorColor(Color.parseColor(mHomeAdapter.getEventCategoriesList().get(i).getCatColor()));
               mPagerTabStrip.setTextColor(Color.BLACK);
            }

            @Override
            public void onPageScrollStateChanged(int i) {

            }
        });
    }


    @Override
    public boolean isTheListEmpty() {
        return (mHomeAdapter == null) || mHomeAdapter.getEventCategoriesList().isEmpty();
    }

    @Override
    public void appendCategories(List<EventCategory> eventCategoryList) {

    }

    /**
     * Call this method from the presenter when login is complete
     */
    @Override
    public void onGoogleAuthenticationSuccess(GoogleApiClient googleApiClient) {
        //lets load an interstitial
        this.mGoogleApiClient = googleApiClient;
        mUser = BaseCore.getInstance().getUser();
        setupNavDrawer();
        loadInterStitialAd();

        mHomePresenter.start();
    }

    private void setupNavDrawer() {
        if (mUser != null) {
            try {
                mTxtUserName.setText(mUser.getUsrName());
                if (mUser.getUsrCoverImgURL() != null && !mUser.getUsrCoverImgURL().isEmpty()) {
                    Picasso.with(getContext()).load(mUser.getUsrCoverImgURL()).fit().into(mImgUserCover);
                }
                if (mUser.getUsrImgURL() != null && !mUser.getUsrImgURL().isEmpty()) {
                    Picasso.with(getContext()).load(mUser.getUsrImgURL()).fit().into(mImgUserProfilePic);
                }
                mTextUserEmail.setText(mUser.getUsrEmail());
            } catch (Exception e) {
                Log.e(TAG, "Error in setting up nav drawer " + e.getMessage());
            }
        }

        mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(MenuItem menuItem) {
                switch (menuItem.getItemId()) {
                    case R.id.nav_coins:
                        mDrawerLayout.closeDrawers();

                        startActivity(new Intent(getContext(), CoinsActivity.class));
                        break;
                    case R.id.nav_friends:
                        mDrawerLayout.closeDrawers();

                        startActivityForResult(Games.Leaderboards.getLeaderboardIntent(mGoogleApiClient,
                                getResources()
                                        .getString(R.string.leaderboard_1)), REQUEST_LEADERBOARD);
                        break;
                    case R.id.nav_achievements:
                        mDrawerLayout.closeDrawers();

                        //startActivity(new Intent(this.getActivity(), AchievementsActivity.class));
                        startActivityForResult(Games.Achievements.getAchievementsIntent(mGoogleApiClient), REQUEST_ACHIEVEMENTS);
                        break;
                    case R.id.nav_notifications:
                        mDrawerLayout.closeDrawers();

                        startActivity(new Intent(getContext(), NotificationsActivity.class));
                        break;
                    case R.id.nav_localEvents:
                        mDrawerLayout.closeDrawers();
                        Intent intentL = new Intent(getContext(), FilterEventsActivity.class);
                        intentL.putExtra("tag", LOCALEVENTS);
                        startActivity(intentL);
                        //     finish();
                        break;
                    case R.id.nav_topEvents:
                        mDrawerLayout.closeDrawers();
                        Intent intentT = new Intent(getContext(), FilterEventsActivity.class);
                        intentT.putExtra("tag", TOPEVENTS);
                        startActivity(intentT);
                        //   finish();
                        break;
                    case R.id.nav_myEvents:
                        mDrawerLayout.closeDrawers();
                        Intent intentM = new Intent(getContext(), FilterEventsActivity.class);
                        intentM.putExtra("tag", MYEVENTSTAG);
                        startActivity(intentM);
                        //    finish();
                        break;
                    case R.id.nav_latestEvents:
                        mDrawerLayout.closeDrawers();
                        Intent intentLA = new Intent(getContext(), FilterEventsActivity.class);
                        intentLA.putExtra("tag", LATESTEVENTS);
                        startActivity(intentLA);
                        // finish();
                        break;
                    case R.id.nav_featuredEvents:
                        mDrawerLayout.closeDrawers();
                        Intent intentF = new Intent(getContext(), FilterEventsActivity.class);
                        intentF.putExtra("tag", FEATUREDEVENTS);
                        startActivity(intentF);
                        //  finish();
                        break;
                    default:
                        return true;
                }
                return true;
            }
        });
    }

    public void loadInterStitialAd() {
        /*if(!GameCore.getInstance().isInterstitialLoaded()){
            GameCore.getInstance().setYoutubevideoId("cEurW7CBzZE");
            startActivity(new Intent(HomeActivity.this, YoutubeIntersitial.class));
        }else{
            GameCore.getInstance().setInterstitialLoaded(false);
        }*/
    }

    /**
     * Call this method from the presenter when login fails
     */
    @Override
    public void onGoogleAuthenticationFailure() {

    }

    @Override
    public Context getContext() {
        return this;
    }

    @Override
    public void loadYouTubeAd(String videoId) {

    }



    /**
     * Called when a view has been clicked.
     *
     * @param v The view that was clicked.
     */
    @Override
    public void onClick(View v) {

    }

    @Override
    protected void onPause() {
        super.onPause();
        // Logs 'app deactivate' App Event.
        AppEventsLogger.deactivateApp(this);
        BaseCore.getInstance().persistInDb();
    }

    @Override
    protected void onActivityResult(int requestCode, int responseCode, Intent intent) {
        super.onActivityResult(requestCode, responseCode, intent);
        if (requestCode == mPlayServicesPresenter.getRcSignIn()) {
            Log.d(TAG, "onActivityResult with requestCode == RC_SIGN_IN, responseCode="
                    + responseCode + ", intent=" + intent);
            mPlayServicesPresenter.setmSignInClicked(false);
            mPlayServicesPresenter.setmResolvingConnectionFailure(false);

            if (responseCode == RESULT_OK) {
                mPlayServicesPresenter.start();
            } else {
                BaseGameUtils.showActivityResultError(this, requestCode, responseCode, R.string.signin_other_error);
            }
        }
    }
}

'showEventCategories'方法为活动设置适配器和viewpager。

以下是适配器的代码:

import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;

import android.support.v13.app.FragmentStatePagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.steigensoft.android.bt_client.R;
import com.steigensoft.android.bt_client.views.fragments.EventGridFragment;
import com.steigensoft.android.model.entities.EventCategory;

import java.util.List;

/**
 * Created by rajiv on 07-04-2015.
 */
public class HomeAdapter extends FragmentStatePagerAdapter {
    private List<EventCategory> mEventCategoryList;

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

    public HomeAdapter(FragmentManager fm, List<EventCategory> eventCategoryList) {
        super(fm);
        this.mEventCategoryList = eventCategoryList;

    }

    /**
     * Return the Fragment associated with a specified position.
     *
     * @param position
     */
    @Override
    public Fragment getItem(int position) {
        return EventGridFragment.newInstance(mEventCategoryList.get(position).getCatId(),mEventCategoryList.get(position).getCatColor());
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return mEventCategoryList.get(position).getCatName();
        //return Titles[position];
    }




    /**
     * Return the number of views available.
     */
    @Override
    public int getCount() {
        //Log.i("GETTING COUNT ", String.valueOf(mEventCategoryList.size()));
        if(mEventCategoryList!=null){
            return mEventCategoryList.size();
        }else return 0;

    }

    public List<EventCategory> getEventCategoriesList() {
        return mEventCategoryList;
    }


}

以下是Fragment的代码:

import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;

import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;

import com.steigensoft.android.bt_client.R;
import com.steigensoft.android.bt_client.mvp.presenters.EventGridPresenter;
import com.steigensoft.android.bt_client.mvp.views.EventGridView;
import com.steigensoft.android.bt_client.utils.RecyclerInsetsDecoration;
import com.steigensoft.android.bt_client.utils.RecyclerViewClickListener;
import com.steigensoft.android.bt_client.views.activities.EventDetailsActivity;
import com.steigensoft.android.bt_client.views.adapters.EventGridAdapter;
import com.steigensoft.android.model.entities.Event;
import com.steigensoft.android.model.entities.EventsWrapper;

import java.util.List;

import butterknife.ButterKnife;
import butterknife.InjectView;


/**
 * A simple {@link Fragment} subclass.
 * Activities that contain this fragment must implement the
 * {@link EventGridFragment.OnFragmentInteractionListener} interface
 * to handle interaction events.
 * Use the {@link EventGridFragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class EventGridFragment extends Fragment implements EventGridView, RecyclerViewClickListener,View.OnClickListener {

    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_CAT_ID = "catId";
    private static final String ARG_CAT_COLOR = "catColor";
    private Long mCatId;
    private String mCatColor;
    private EventGridAdapter mEventGridAdapter;
    private EventGridPresenter mEventPresenter;
    private GridLayoutManager mGridLayoutManager;
    public float mBackgroundTranslation;
    int pastVisiblesItems, visibleItemCount, totalItemCount;
    @InjectView(R.id.fragment_event_grid_progress)
    ProgressBar mProgressBar;
    @InjectView(R.id.fragment_event_grid_recycler)
    RecyclerView mRecyclerView;
    private ImageView mCoverImage;
    private OnFragmentInteractionListener mListener;

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param catId Parameter 1
     * @return A new instance of fragment EventGrid.
     */
    // TODO: Rename and change types and number of parameters
    public static EventGridFragment newInstance(Long catId,String catColor) {
        EventGridFragment fragment = new EventGridFragment();
        Bundle args = new Bundle();
        args.putLong(ARG_CAT_ID, catId);
        args.putString(ARG_CAT_COLOR,catColor);
        fragment.setArguments(args);
        return fragment;
    }

    public EventGridFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {

        //Todo investigate more on lifecycle of a fragment, whether onCreate is better or OnCreateView
        super.onCreate(savedInstanceState);

    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        // Inflate the layout for this fragment
        View fragmentEvent =  inflater.inflate(R.layout.fragment_event_grid, container, false);
        ButterKnife.inject(this, fragmentEvent);
       // mRecyclerView.setLayoutManager(new GridLayoutManager(fragmentEvent.getContext(),));
        mRecyclerView.addItemDecoration(new RecyclerInsetsDecoration(this.getContext()));
        //mRecyclerView.setOnScrollListener(recyclerScrollListener);


        if (getArguments() != null) {
            mCatId = getArguments().getLong(ARG_CAT_ID);
            mCatColor = getArguments().getString(ARG_CAT_COLOR);
        }
        if (savedInstanceState == null) {
            mEventPresenter = new EventGridPresenter(this);
        } else {
            EventsWrapper eventsWrapper = (EventsWrapper) savedInstanceState.getSerializable("events_wrapper" + mCatId);
            mEventPresenter = new EventGridPresenter(this,eventsWrapper);
        }


        return fragmentEvent;
    }




/* //Todo : Need to take a deeper look into Attach/Detach events
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnFragmentInteractionListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }*/

    @Override
    public void onStart(){
        super.onStart();
        mEventPresenter.start(mCatId);
    }

    @Override
    public void onStop(){
        super.onStop();
        mEventPresenter.stop();
    }


    @Override
    public void showEvents(List<Event> eventList) {

        mEventGridAdapter = new EventGridAdapter(eventList);
        mEventGridAdapter.setRecyclerListListener(this);
        mRecyclerView.setAdapter(mEventGridAdapter);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {

        super.onSaveInstanceState(outState);

        if (mEventGridAdapter != null) {

            outState.putSerializable("events_wrapper" + mCatId,
                    new EventsWrapper(mEventGridAdapter.getEventList()));

        }

    }

    @Override
    public void showLoading() {
        mProgressBar.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideLoading() {
        mProgressBar.setVisibility(View.GONE);
    }

    @Override
    public void showError(String error) {
        //TODO
    }

    @Override
    public void hideError() {

    }

    @Override
    public void showLoadingLabel() {

    }

    @Override
    public void hideActionLabel() {

    }

    @Override
    public boolean isTheListEmpty() {
        return (mEventGridAdapter == null) || mEventGridAdapter.getEventList().isEmpty();
    }

    @Override
    public void appendEvents(List<Event> eventList) {
        //TODO when we will be invoking paging system
    }

    @Override
    public Context getContext() {
        return this.getActivity();
    }

    @Override
    public void loadYouTubeAd(String videoId) {

    }


    @Override
    public void onClick(View v, int position, float x, float y) {
        Intent eventDetailActivityIntent = new Intent (
                getContext(), EventDetailsActivity.class);
        //TODO : Put some nice transition effects here later
        eventDetailActivityIntent.putExtra("event_obj", mEventGridAdapter.getEventList().get(position));
        eventDetailActivityIntent.putExtra("event_color",mCatColor );
        startActivity(eventDetailActivityIntent);
    }

    @Override
    public void onClick(View v) {

    }

    /**
     * This interface must be implemented by activities that contain this
     * fragment to allow an interaction in this fragment to be communicated
     * to the activity and potentially other fragments contained in that
     * activity.
     * <p>
     * See the Android Training lesson <a href=
     * "http://developer.android.com/training/basics/fragments/communicating.html"
     * >Communicating with Other Fragments</a> for more information.
     */
    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        public void onFragmentInteraction(Uri uri);
    }

}

错误:

Caused by: java.lang.IllegalStateException: Fragment EventGridFragment{2fbf162b} is not currently in the FragmentManager
            at android.app.FragmentManagerImpl.saveFragmentInstanceState(FragmentManager.java:595)
            at android.support.v13.app.FragmentStatePagerAdapter.destroyItem(FragmentStatePagerAdapter.java:140)
            at android.support.v4.view.ViewPager.setAdapter(ViewPager.java:417)
            at com.steigensoft.android.bt_client.views.activities.HomeActivity.showEventCategories(HomeActivity.java:214)
            at com.steigensoft.android.bt_client.mvp.presenters.HomePresenter.onAllEventsReceived(HomePresenter.java:61)

0 个答案:

没有答案