firebase / FirebaseUI-Android

Optimized UI components for Firebase
https://firebaseopensource.com/projects/firebase/firebaseui-android/
Apache License 2.0
4.63k stars 1.84k forks source link

Firebase RecyclerView crash when closing an activity started by intent with 2 Fragments in FragmentStatePagerAdapter #648

Closed lumleon closed 7 years ago

lumleon commented 7 years ago

Welcome to FirebaseUI and thanks for submitting an issue!

Please take a look at open issues, as well as resolved issues, to see if your issue is either already being addressed, or has been solved by someone else.

If not, please feel free to fill in the following info so we can help faster!

Step 1: Are you in the right place?

Step 2: Describe your environment

Step 3: Describe the problem:

Steps to reproduce:

  1. create 2 fragments in FragmentStatePagerAdapter
  2. create FirebaseRecyclerAdapter in the 2 fragments and add clicklistener for the entire item
  3. scroll to the end of the list view and click
  4. start another activity by intent with the post key to show the child post details
  5. click back and it will crash as the following log

Observed Results:

Relevant Code:


  // TODO(you): code here to reproduce the problem

    public void init(){

        /** TODO: Insert all the code from the HomeActivity’s onCreate() method after the setContentView method call */

        // Create the adapter that will return a fragment for each of the two
        // primary sections of the activity.
        mSectionsPagerAdapter = new FragmentStatePagerAdapter(getFragmentManager()) {

            private final Fragment[] mFragments = new Fragment[] {
                    new DailyTipsActivePostsFragment(),
                 //   new DailyRealTipsPostsFragment(),
                 //   new BankerOldPostsFragment(),
                    //  new MyTopPostsFragment(),
            };
            private final String[] mFragmentNames = new String[] {

                    getString(R.string.heading_daily_active),
                //    getString(R.string.heading_daily_real),

            };

            @Override
            public Fragment getItem(int position) {

                return mFragments[position];

            }

            @Override
            public int getCount() {

                return mFragments.length;

            }

            @Override
            public CharSequence getPageTitle(int position) {
                return mFragmentNames[position];
            }

        };

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) rootView.findViewById(R.id.container);
        mViewPager.setAdapter(mSectionsPagerAdapter);
        TabLayout tabLayout = (TabLayout) rootView.findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(mViewPager);

        // Button launches BankerPostNewActivity for userrole = admin
        if( getUserRole().equals("admin")){

            rootView.findViewById(R.id.fab_new_post).setVisibility(View.VISIBLE);
            rootView.findViewById(R.id.fab_new_post).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(getActivity(), DailyNewActivity.class));
            }
        });

        }
    }

// code for recycler adapter
 public void setupAdapter(){

        // Set up FirebaseRecyclerAdapter with the Query
        Query postsQuery = getQuery(mDatabaseReference);

        mAdapter = new FirebaseRecyclerAdapter<RaceSchedulePost, RaceSchedulePostListViewHolder>(
                RaceSchedulePost.class,
                R.layout.item_dailytipspost,
                RaceSchedulePostListViewHolder.class,
                postsQuery  ) {

            @Override
            protected void populateViewHolder(final RaceSchedulePostListViewHolder viewHolder, final RaceSchedulePost model, int position) {

                final DatabaseReference postRef = getRef(position);

                //Method for setter Feb 8, 2017
                viewHolder.setRacedate(model.getRacedate());
                viewHolder.setLocation(model.getLocation());
                viewHolder.setTurf(model.getTurf());
                viewHolder.setAwt(model.getAwt());
                viewHolder.setTitle(model.getTitle());

                viewHolder.setTipsresult(model.getTipsresult());

                viewHolder.setStatus(model.getStatus());

                // Set click listener for the whole post view
                final String postKey = postRef.getKey();

             //set onclick listener for entire post
         viewHolder.mView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                //set the postkey to field
                mPostKey = postKey;

                mStatusKey =model.getStatus();

                //Toast.makeText(getActivity(), mPostKey, Toast.LENGTH_SHORT).show();

                //set click counter
                DatabaseReference globalPostRef = mDatabaseReference.child(CHILD_DAILYPOST).child(mPostKey);
                onPostClicked(globalPostRef);

                //if today or active post, check balance and charge rate and then ask deduct balance to view post

                // Launch PostDetailActivity
                    Intent intent = new Intent(getActivity(), DailyRaceTipsActivity.class);
                    intent.putExtra(DailyRaceTipsActivity.EXTRA_POST_KEY, mPostKey);
                    intent.putExtra(DailyRaceTipsActivity.EXTRA_STATUS_KEY, mStatusKey);

                startActivity(intent);

            }
         });

   mAdapter.notifyDataSetChanged();

        mRecycler.setAdapter(mAdapter);

        mAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
            @Override
            public void onItemRangeInserted(int positionStart, int itemCount) {
                super.onItemRangeInserted(positionStart, itemCount);
                int pollCount = mAdapter.getItemCount();
                int lastVisiblePosition = mManager.findLastCompletelyVisibleItemPosition();

                // If the recycler view is initially being loaded or the user is at the bottom of the list, scroll
                // to the bottom of the list to show the newly added message.
                if (lastVisiblePosition == -1 ||
                        (positionStart >= (pollCount - 1) && lastVisiblePosition == (positionStart - 1))) {
                    mRecycler.scrollToPosition(positionStart);
                }
            }
        });

    }

[reproduce.zip](https://github.com/firebase/FirebaseUI-Android/files/869913/reproduce.zip)
stevedj commented 7 years ago

Hi, I also got this problem

I create a viewpager with fragments inside it, in active fragment, there is a recycler view, I opened a new activity and do some stuff in there, and click back, I got several errors,

I would like to help if there is anything that I can do

Best Regards Steve

stevedj commented 7 years ago

Hi all,

for additional info, I have tried to cleanup when it is on destroy/stop but, it still giving me that error

Is there anyone who encounter the same problem?

Best regards Steve

SUPERCILEX commented 7 years ago

@stevedj @lumleon The error you're getting isn't because of FirebaseUI, it's an issue with how you're using the RecyclerView:

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 4(offset:4).state:5

I've had this issue before and here was my solution: https://issuetracker.google.com/issues/37135118#comment9

Make sure not to do anything funky with ViewHolders and you should be good. Hope this helps! 😄

SUPERCILEX commented 7 years ago

@samtstern I believe this issue can be closed due to inactivity.