Czechnology
Czechnology

Reputation: 14992

ViewPager's PageAdapter get reset on orientation change

I'm using a ViewPager for a multiple-choice exam app, which chooses out randomly thirty questions out of a bigger set. I do this in the PageAdapter that is supplying the pages to the ViewPager.

The problem is that when an orientation change occurs, not only the pager but also the adapter gets reloaded - I know how to save the current pager position but when the adapter gets reset, it also chooses new questions from the set. What would be the proper way to handle this?

Also, side question - what would be the best way to register the choices on the RadioGroups? Directly by click or in a different way?

I'm fairly new to the Android app developement.


Activity:

public class MyActivity extends SherlockActivity {
    ActionBar actionBar;
    ViewPager pager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        pager = new ViewPager(this);
        setContentView(pager);
        QuestionsAdapter adapter = new QuestionsAdapter(this);
        pager.setAdapter(adapter);

        int position = 0;
        if (savedInstanceState != null) {
            position = savedInstanceState.getInt("Q_NUMBER");
        }         
        pager.setCurrentItem(position);
    }

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        int position = pager.getCurrentItem();
        savedInstanceState.putInt("Q_NUMBER", position);
    }
}

Adapter:

class QuestionsAdapter extends PagerAdapter {
    Context context;
    QuestionsHelper dbQuestions;
    boolean exam;
    List<HashMap<String,Object>> examQuestions;

    public QuestionsAdapter(Context context, boolean exam) {
        this.context = context;
        this.examQuestions = GetQuestionsFromDB(30);
    }

    public Object instantiateItem(View collection, int position) {
        LayoutInflater inflater = (LayoutInflater) collection.getContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View view;
        HashMap<String,Object> q;

        view = inflater.inflate(R.layout.exam_question_layout, null);
        q = getQuestion(position+1);

        ((TextView)view.findViewById(R.id.q_number)).setText(Integer.toString(position+1)+".");
        ((TextView)view.findViewById(R.id.q_question)).setText(q.get("question").toString());
        ((RadioButton)view.findViewById(R.id.q_answer_a)).setText(q.get("answer_a").toString());
        ((RadioButton)view.findViewById(R.id.q_answer_b)).setText(q.get("answer_b").toString());
        ((RadioButton)view.findViewById(R.id.q_answer_c)).setText(q.get("answer_c").toString());

        ((ViewPager)collection).addView(view, 0);
        return view;
    }
}

Upvotes: 7

Views: 7728

Answers (2)

user
user

Reputation: 87064

I know how to save the current pager position but when the adapter gets reset, it also chooses new questions from the set. What would be the proper way to handle this?

Your questions should really have an id to uniquely identify them. I'm not sure how you get them from the database but when that would happen you would need to store their ids. Also:

  • Your adapter should have a long array(or integer) holding 30 values representing the ids of the current selected batch of questions
  • You'll need to implement the following logic in the adapter: if the long array from the previous point is null then assume it's a clean start and get a new set of 30 questions. If the long array is non null then we are facing a restore from a configuration change and you'll need to use those ids to get the proper questions from the database instead of a random batch
  • In the Activity you'll save the long array of the adapter in the onSaveInstanceState() method(savedInstanceState.putLongArray)
  • In the onCreate method of the Activity, when you create the adapter, you'll check the savedInstanceState Bundle to see if it is non-null and it has the long array and set that on the adapter(so it will know which questions to get)

what would be the best way to register the choices on the RadioGroups? Directly by click or in a different way?

You could use the above method, or create a custom class with Parcelable like it has already been recommended to you in the comments.

Upvotes: 4

Meghal Shah
Meghal Shah

Reputation: 405

Screen Rotation will redraw the entire screen in the new orientation, we can prevent it with overriding configuration changes.

add android:configChanges="orientation|screenSize" under your screen declaration in Android Manifest

 android:configChanges="orientation|screenSize"

And Override onConfigurationChanged(Configuration) in your activity like

 @Override
 public void onConfigurationChanged(Configuration newConfig) {
     super.onConfigurationChanged(newConfig);
 }

Upvotes: 12

Related Questions