1

What I'm trying to do:

Have users input data on 3 different fragments, then on the 4th fragment the user will review all data input into the first 3 fragments before submitting to a database.

The issue I'm having:

Every method I've tried to set or get from the EditText's creates a NullPointerException

My question:

For what I'm trying to do, what is the correct method to call for the text value of an EditText from one fragment, and set that text in an EditText in another fragment anytime a page is changed?

Notes:

I've simplified the code down to only reflect one EditText on each fragment for ease of replication and for ease of dissecting code.

Code:

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.widget.EditText;

public class SwipeEnterResults extends FragmentActivity {

ResultsPagerAdapter mResultsPagerAdapter;
ViewPager mViewPager;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.swipe_enter_results);

    mResultsPagerAdapter = new ResultsPagerAdapter(getSupportFragmentManager());
    mViewPager = (ViewPager) findViewById(R.id.pager);      
    mViewPager.setAdapter(mResultsPagerAdapter); 
}

public void onResume() {
    super.onResume();
    //Declare EditText(s)

    final EditText txt1= (EditText) mViewPager.findViewById(R.id.txt1);
    final EditText txt2= (EditText) mViewPager.findViewById(R.id.txt2);
    final EditText txt3= (EditText) mViewPager.findViewById(R.id.txt3);

    final EditText rvw1= (EditText) mViewPager.findViewById(R.id.rvw1);
    final EditText rvw2= (EditText) mViewPager.findViewById(R.id.rvw2);
    final EditText rvw3= (EditText) mViewPager.findViewById(R.id.rvw3);


    mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {

            rvw1.setText(txt1.getText().toString());
            rvw2.setText(txt2.getText().toString());
            rvw3.setText(txt3.getText().toString());                
        }
        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) { }
        @Override
        public void onPageScrollStateChanged(int arg0) { }
    });
}

public class ResultsPagerAdapter extends FragmentPagerAdapter{

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

    @Override
    public Fragment getItem(int position) {
        Fragment f = new Fragment();

        switch (position) {
        case 0:
            f = new Swipe1();
            break;
        case 1:
            f = new Swipe2();
            break;
        case 2:
            f = new Swipe3();
            break;
        case 3:
            f = new SwipeReviewResults();
            break;
        }

        return f;
    }

    @Override
    public int getCount() {
        return 4;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        switch (position) {
        case 0:
            return getString(R.string.str1);
        case 1:
            return getString(R.string.str2);
        case 2:
            return getString(R.string.str3);
        case 3:
            return getString(R.string.strReview);
        default:
            return "Page " + (position + 1);
        }
    }
}
}
Jim
  • 271
  • 6
  • 20

4 Answers4

1

A couple of things:

  1. Is it possible that the EditTexts in the Activity are null because you are trying to reference them (via their IDs in the view) before all of the fragments and their views have been created by the adapter? Furthermore, it would appear that each time the getItem method of the ResultsPagerAdapter is called, a new fragment with its own view is created... so your Activity could be referencing stale EditText views when new fragment views are created.

  2. Your Activity shouldn't have to be concerned with what views are present in each fragment and the logic surrounding them. It would be better to have each fragment handle the reference to its own views and manage the logic surrounding them. What you could do is have a central cache where the EditTexts values are stored/retrieved by the fragments. For instance, in the onPause() method of a Swipe fragment you could store its EditText value in the cache, and in the onResume() method of the SwipeReviewResults fragment could pull all updated EditText values from the cache.

  3. In your switch statement of the adapter, you should make use of the default block to return an empty new Fragment() instead of unnecessarily creating it upfront.

I hope this helps you out.

Stephen Asherson
  • 1,557
  • 14
  • 23
  • Like this: `@Override public Fragment getItem(int position) { Fragment f; switch (position) { case 0: f = new SwipeChemicalsApplied(); break; case 1: f = new SwipeRaw(); break; case 2: f = new SwipeFinished(); break; case 3: f = new SwipeReviewResults(); break; default: f = new Fragment(); break; } return f; }` – Jim May 16 '13 at 14:33
  • What's the best way to add the fragments to the ViewPager before everything is loaded? ALso, I am unfamiliar with storing into cache memory, but that seems like that would be a good option and am currently going to explore that. I appreciate your help and will let you know what kind of results I get. Hopefully it works out for me! – Jim May 16 '13 at 14:42
  • Better switch statement. To answer your other question, you shouldn't need to worry about the ViewPager being added before everything else; remove references to the EditTexts in your Activity, add the ViewPager as you are but allow each Fragment to manage the reference to its EditText in the `onCreateView` lifecycle method. For caching, you could always use the Application class as a cache to store global state, but please read this first: [link](http://stackoverflow.com/questions/4585627/android-application-class-lifecycle). Please mark my answer as correct if it has helped you :) Thanks. – Stephen Asherson May 17 '13 at 06:00
  • I ended up just putting the code in an if statement with a condition of position being 3. It worked out, but I do appreciate the input because that could help me out in the future on other projects. – Jim May 21 '13 at 14:22
0

Don't make the EditTexts final. Try the following code in place of your current onResume:

EditText txt1= (EditText) mViewPager.findViewById(R.id.txt1);
EditText txt2= (EditText) mViewPager.findViewById(R.id.txt2);
EditText txt3= (EditText) mViewPager.findViewById(R.id.txt3);

EditText rvw1= (EditText) mViewPager.findViewById(R.id.rvw1);
EditText rvw2= (EditText) mViewPager.findViewById(R.id.rvw2);
EditText rvw3= (EditText) mViewPager.findViewById(R.id.rvw3);
TronicZomB
  • 8,667
  • 7
  • 35
  • 50
0

Probably your ViewPager doesn't have EditTexts with ids R.id.txt1, R.id.rvw1, ...

Insure you have defined all EditTexts in swipe_enter_results.xml file. Otherwise some of objects (maybe all) will be equal to null and you'll get a NullPointerException.

Dmitry Guselnikov
  • 1,048
  • 1
  • 8
  • 21
  • There are 4 separate xml layouts with the different ID's. That's not the issue. With my full design it's near 60 total EditText's and every single one of them ends up null. – Jim May 16 '13 at 14:30
0

I ended up trying a couple things. I added mViewPager.setOffscreenPageLimit(3); and then just put my code in an if statement with a condition of position == 3 and that seems to have solved all my issues with the nullpointerexception. Thanks everyone for the help!

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.widget.CheckBox;
import android.widget.EditText;

public class SwipeEnterResults extends FragmentActivity {

ResultsPagerAdapter mResultsPagerAdapter;
ViewPager mViewPager;

//Declare EditText for reviewing data on Fragment SwipeReviewResults
EditText txt1;
EditText rvw1;
EditText txt2;
EditText rvw2;
EditText txt3;
EditText rvw3;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.swipe_enter_results);

    //Set up ViewPager and allow app to hold prior pages when off screen
    mResultsPagerAdapter = new ResultsPagerAdapter(getSupportFragmentManager());
    mViewPager = (ViewPager) findViewById(R.id.pager);      
    mViewPager.setAdapter(mResultsPagerAdapter);
    mViewPager.setOffscreenPageLimit(3);

    //When SwipeReviewResults is displayed, fill EditText's with data from other fragments
    mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {

            if (position == 3) {
                //set values to EditTexts to pull data from 3 entry fragments and display in SwipeReviewResults
                EditText txt1 = (EditText) mViewPager.findViewById(R.id.txt1);
                EditText rvw1 = (EditText) mViewPager.findViewById(R.id.rvw1);
                EditText txt2 = (EditText) mViewPager.findViewById(R.id.txt2);
                EditText rvw2 = (EditText) mViewPager.findViewById(R.id.rvw2);
                EditText txt3 = (EditText) mViewPager.findViewById(R.id.txt3);
                EditText rvw3 = (EditText) mViewPager.findViewById(R.id.rvw3);


                //Set EditText's on SwipeReviewResults
                rvw1.setText(txt1.getText().toString());
                rvw2.setText(txt2.getText().toString());
                rvw3.setText(txt3.getText().toString());

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

public class ResultsPagerAdapter extends FragmentPagerAdapter{

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

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

        switch (position) {
        case 0:
            f = new Swipe1();
            break;
        case 1:
            f = new Swipe2();
            break;
        case 2:
            f = new Swipe3();
            break;
        case 3:
            f = new SwipeReviewResults();
            break;
        default:
            f = new Fragment();
            break;
        }

        return f;
    }

    @Override
    public int getCount() {
        return 4;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        switch (position) {
        case 0:
            return getString(R.string.str1);
        case 1:
            return getString(R.string.str2);
        case 2:
            return getString(R.string.str3);
        case 3:
            return getString(R.string.strReview);
        default:
            return "Page " + (position + 1);
        }
    }
}
}
Jim
  • 271
  • 6
  • 20