问题
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);
}
}
}
}
回答1:
A couple of things:
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 theResultsPagerAdapter
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.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 aSwipe
fragment you could store its EditText value in the cache, and in theonResume()
method of theSwipeReviewResults
fragment could pull all updated EditText values from the cache.In your switch statement of the adapter, you should make use of the
default
block to return an emptynew Fragment()
instead of unnecessarily creating it upfront.
I hope this helps you out.
回答2:
Don't make the EditText
s 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);
回答3:
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.
回答4:
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);
}
}
}
}
来源:https://stackoverflow.com/questions/16574446/reference-to-edittext-in-viewpager-creates-null-pointer-exception