0

After adding a ViewPager and FragmentStatePagerAdapter, the new CrimePagerActivity does start and I can swipe forward normally, but if I try to swipe to the Crime where I came from, the app freezes for a second then restarts the app back to the list view.

For example, if I start at Crime 3, I can move forward to 4 (or backwards to 2), but if I move back to 3, it will freeze and crash. Please see the code and stack trace below:

CrimePagerActivity.java

 public class CrimePagerActivity extends AppCompatActivity {
    private ViewPager mViewPager;
    private List<Crime> mCrimes;

    private static final String EXTRA_CRIME_ID =
            "com.bignerdranch.android.crime_id";

    public static Intent newIntent(Context packageContext, UUID crimeID) {
        Intent intent = new Intent(packageContext, CrimePagerActivity.class);
        intent.putExtra(EXTRA_CRIME_ID, crimeID);
        return intent;
    }

    @Override
    public void onCreate(Bundle savedInstancestate) {
        super.onCreate(savedInstancestate);
        setContentView(R.layout.activity_crime_pager);

        UUID crimeId = (UUID) getIntent().getSerializableExtra(EXTRA_CRIME_ID);

        mViewPager = (ViewPager) findViewById(R.id.crime_view_pager);

        mCrimes = CrimeLab.get(this).getCrimes();
        FragmentManager fragmentManager = getSupportFragmentManager();

        mViewPager.setAdapter(new FragmentStatePagerAdapter(fragmentManager) {

            @Override
            public Fragment getItem(int position) {
                Log.d("Fragment", "Position is " + position);
                Crime crime = mCrimes.get(position);
                Log.d("Fragment getItem", "Title is " + crime.getTitle());
                Log.d("Fragment getItem", "Title is " + crime.isSolved());
                return CrimeFragment.newInstance(crime.getId());
            }

            @Override
            public int getCount() {
                return mCrimes.size();
            }
        });

        for (int i = 0; i < mCrimes.size(); i++) {
            if (mCrimes.get(i).getId().equals(crimeId)) {
                mViewPager.setCurrentItem(i);
                break;
            }
        }

    }
}

CrimeFragment.java

    public class CrimeFragment extends Fragment {
       private Crime mCrime;
    private EditText mTitleField;
    private Button mDateButton;
    private CheckBox mSolvedCheckBox;

    private static final String ARG_CRIME_ID = "crime_id";

    public static CrimeFragment newInstance (UUID crime_id) {
        Bundle args = new Bundle();
        args.putSerializable(ARG_CRIME_ID, crime_id);

        CrimeFragment fragment = new CrimeFragment();
        fragment.setArguments(args);
        return fragment;
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        UUID crimeId = (UUID) getArguments().getSerializable(ARG_CRIME_ID);
        mCrime = CrimeLab.get(getActivity()).getCrime(crimeId);

    }// END OF onCreate()

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_crime, container, false);
        mTitleField = (EditText) v.findViewById(R.id.crime_title);
        mTitleField.setText(mCrime.getTitle());
        mTitleField.addTextChangedListener(new TextWatcher() {

            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                //Intentionally left blank
            }

            @Override
            public void onTextChanged(CharSequence s, int i, int i1, int i2) {
                mTitleField.setText(s.toString());
            }

            @Override
            public void afterTextChanged(Editable editable) {
                //Intentionally left blank
            }
        });// END OF adding TextChangeListener to mTitleField

        mDateButton = (Button) v.findViewById(R.id.crime_date);
        mDateButton.setText(mCrime.getDate().toString());
        mDateButton.setEnabled(false);

        mSolvedCheckBox = (CheckBox) v.findViewById(R.id.crime_solved);
        mSolvedCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                mCrime.setSolved(isChecked);
            }
        });// END OF mSolvedCheckBox onCheckListener

        return v;
    }// END OF onCreateView()

}// END OF CrimeFragment class

Stack trace of error: 11-02 13:23:23.906 4592-4592/com.bignerdranch.android.criminalintent E/AndroidRuntime: FATAL EXCEPTION: main Process: com.bignerdranch.android.criminalintent, PID: 4592 java.lang.StackOverflowError: stack size 8MB at com.bignerdranch.android.criminalintent.CrimeFragment$1.beforeTextChanged(CrimeFragment.java:0) at android.widget.TextView.sendBeforeTextChanged(TextView.java:8268) at android.widget.TextView.setText(TextView.java:4356) at android.widget.TextView.setText(TextView.java:4313) at android.widget.EditText.setText(EditText.java:84) at android.widget.TextView.setText(TextView.java:4288) at com.bignerdranch.android.criminalintent.CrimeFragment$1.onTextChanged(CrimeFragment.java:67) at android.widget.TextView.sendOnTextChanged(TextView.java:8318) at android.widget.TextView.setText(TextView.java:4459) at android.widget.TextView.setText(TextView.java:4313) at android.widget.EditText.setText(EditText.java:84) at android.widget.TextView.setText(TextView.java:4288) at com.bignerdranch.android.criminalintent.CrimeFragment$1.onTextChanged(CrimeFragment.java:67) at android.widget.TextView.sendOnTextChanged(TextView.java:8318) at android.widget.TextView.setText(TextView.java:4459) at android.widget.TextView.setText(TextView.java:4313) at android.widget.EditText.setText(EditText.java:84) at android.widget.TextView.setText(TextView.java:4288) at com.bignerdranch.android.criminalintent.CrimeFragment$1.onTextChanged(CrimeFragment.java:67) at android.widget.TextView.sendOnTextChanged(TextView.java:8318) at android.widget.TextView.setText(TextView.java:4459) at android.widget.TextView.setText(TextView.java:4313) at android.widget.EditText.setText(EditText.java:84) at android.widget.TextView.setText(TextView.java:4288) at com.bignerdranch.android.criminalintent.CrimeFragment$1.onTextChanged(CrimeFragment.java:67) at android.widget.TextView.sendOnTextChanged(TextView.java:8318) at android.widget.TextView.setText(TextView.java:4459) at android.widget.TextView.setText(TextView.java:4313) at android.widget.EditText.setText(EditText.java:84) at android.widget.TextView.setText(TextView.java:4288) at com.bignerdranch.android.criminalintent.CrimeFragment$1.onTextChanged(CrimeFragment.java:67) at android.widget.TextView.sendOnTextChanged(TextView.java:8318) at android.widget.TextView.setText(TextView.java:4459) at android.widget.TextView.setText(TextView.java:4313) at android.widget.EditText.setText(EditText.java:84) at android.widget.TextView.setText(TextView.java:4288) at com.bignerdranch.android.criminalintent.CrimeFragment$1.onTextChanged(CrimeFragment.java:67) at android.widget.TextView.sendOnTextChanged(TextView.java:8318) at android.widget.TextView.setText(TextView.java:4459) at android.widget.TextView.setText(TextView.java:4313) at android.widget.EditText.setText(EditText.java:84) at android.widget.TextView.setText(TextView.java:4288) at com.bignerdranch.android.criminalintent.CrimeFragment$1.onTextChanged(CrimeFragment.java:67) at android.widget.TextView.sendOnTextChanged(TextView.java:8318) at android.widget.TextView.setText(TextView.java:4459) at android.widget.TextView.setText(TextView.java:4313) at android.widget.EditText.setText(EditText.java:84) at android.widget.TextView.setText(TextView.java:4288) at com.bignerdranch.android.criminalintent.CrimeFragment$1.onTextChanged(CrimeFragment.java:67) at android.widget.TextView.sendOnTextChanged(TextView.java:8318) at android.widget.TextView.setText(TextView.java:4459) at android.widget.TextView.setText(TextView.java:4313) at android.widget.EditText.setText(EditText.java:84) at android.widget.TextView.setText(TextView.java:4288) at com.bignerdranch.android.criminalintent.CrimeFragment$1.onTextChanged(CrimeFragment.java:67) at android.widget.TextView.sendOnTextChanged(TextView.java:8318) at android.widget.TextView.setText(TextView.java:4459) at android.widget.TextView.setText(TextView.java:4313) at android.widget.EditText.setText(EditText.java:84) at android.widget.TextView.setText(TextView.java:4288) at com.bignerdranch.android.criminalintent.CrimeFragment$1.onTextChanged(C 11-02 13:23:23.998 4592-4592/com.bignerdranch.android.criminalintent E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 1896744) 11-02 13:23:24.007 4592-4592/com.bignerdranch.android.criminalintent E/AndroidRuntime: Error reporting crash android.os.TransactionTooLargeException: data parcel size 1896744 bytes at android.os.BinderProxy.transactNative(Native Method) at android.os.BinderProxy.transact(Binder.java:505) at android.app.ActivityManagerProxy.handleApplicationCrash(ActivityManagerNative.java:4427) at com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException(RuntimeInit.java:90) at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693) at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690)

Please assist.

Dileep Patel
  • 1,988
  • 2
  • 12
  • 26
Kasvan
  • 36
  • 5

2 Answers2

1

mViewPager.setCurrentItem(i) is automatically done by the fragmentStatePagerAdapeter.Remove this loop statment.It is causing Adding the view to itself it is probably cause of a infinite recursion.

 for (int i = 0; i < mCrimes.size(); i++) {
        if (mCrimes.get(i).getId().equals(crimeId)) {
            mViewPager.setCurrentItem(i);
            break;
        }
    }

Also before updating textview remove the listner then add to prevent stackoverflow error

TextWatcher textWatcher=new TextWatcher() {

    @Override
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        //Intentionally left blank
    }

    @Override
    public void onTextChanged(CharSequence s, int i, int i1, int i2) {
        mTitleField.removeTextChangedListener(textWatcher);
        mTitleField.setText(s.toString());
        mTitleField.addTextChangedListener(txtwt);
    }

    @Override
    public void afterTextChanged(Editable s) {

    }

};
mTitleField.addTextChangedListener(textWatcher);
Sharath kumar
  • 4,064
  • 1
  • 14
  • 20
  • 2
    Where is recursive looping only selecting one page by checking crimeId and after that break loop – J Ramesh Nov 02 '17 at 11:42
  • Dont do that..the fragmentStatePagerAdapeter automatically does that for you. – Sharath kumar Nov 02 '17 at 11:44
  • @Pritesh-ɐʎıɥpɐΛɥsǝʇᴉɹꓒ just look at the statment.Running for loop without any reason will cause UI lag.he is not doing anything inside loop apart from setCurrentItem which is done by the fragmentStatePagerAdapeter itself – Sharath kumar Nov 02 '17 at 11:48
0

Comment from J Ramesh is correct.

I removed the code in the onTextChanged method and it fixed the issue.

Before that, I did try Anonymous' answer but did not work.

Without the for-loop, the first fragment that the ViewPager displays is always the first item in the list.

The list (in the launcher activity) is using a RecyclerView with each ViewHolder having an onclick listener which starts a new CrimePagerActivity.

The ViewHolder only has a single Crime object and not the list.

I suppose the adapter can pass in the position of the crime object along with the actual crime object when binding the ViewHolder to it's layout. Then the ViewHolder's onClickListener can add that to the intent it uses to start the CrimePageActivity so that the ViewPager can start on the correct Crime/Fragment without the for-loop. Edited: I just implemented this change and it works. P.S i started learning android dev two weeks ago so I ask if you can please indulge my rudimentary approaches.

Thank you very much for your assistance. I want to like or upvote you comment but not sure how to. New to this forum.

Kasvan
  • 36
  • 5