androidandroid-fragmentsandroid-viewpagerandroid-loadermanager

viewpager first item doesn't show content


I know there is lots of threads talk about first item problems in viewpager, I searched many time about my issue but no way I just lose time. would you help me, please ?

I use FragmentStatePagerAdapter , fragment and loader manager that add radio buttons dynamically. the first iitem in view pager doesn't show radio buttons until I swipe to third item and back again to the first one.

screen

Image

Fragment:

    package mohalim.android.egybankstest.Fragments;

import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;

import mohalim.android.egybankstest.Database.AppContract;
import mohalim.android.egybankstest.Models.Choice;
import mohalim.android.egybankstest.Models.Question;
import mohalim.android.egybankstest.R;
import mohalim.android.egybankstest.ResultActivity;

public class QuizFragement extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>{
    private static final String UPDATE = "update";
    private static final int GET_CHOICES_LOADER_ID = 100;
    private static final int UPDATE_CHOSEN_ANSWER_LOADER_ID = 101;
    private static final String SELECTED_QUIZ = "selected_quiz";

    ArrayList<Question> questions;
    ArrayList<Choice> choices;
    int questionPosition;
    String selectedQuiz;

    RadioGroup radioGroup;
    TextView questionText;


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        choices = new ArrayList<>();
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.quiz_fragment, container, false);
        questionText = view.findViewById(R.id.m);
        radioGroup = view.findViewById(R.id.choices_radio);
        radioGroup.removeAllViews();

        questionText.setText(questions.get(questionPosition).getQuestion_text());





        if (questionPosition == 0){
            getActivity().getSupportLoaderManager()
                    .initLoader(GET_CHOICES_LOADER_ID,null,this)
                    .forceLoad();
        }else {
            getActivity().getSupportLoaderManager()
                    .restartLoader(GET_CHOICES_LOADER_ID,null,this)
                    .forceLoad();

        }





        /**
         * end the session
         */
        FloatingActionButton fab = view.findViewById(R.id.end_session);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getActivity(), ResultActivity.class);
                intent.putExtra(SELECTED_QUIZ,selectedQuiz);
                startActivity(intent);
                getActivity().finish();
            }
        });



        return view;
    }


    @NonNull
    @Override
    public Loader<Cursor> onCreateLoader(int id, @Nullable final Bundle args) {
        if (id==GET_CHOICES_LOADER_ID){

            Uri choicesUri = AppContract.ChoiceEntry.CONTENT_URI
                    .buildUpon()
                    .appendPath(String.valueOf(questions.get(questionPosition).getQuestionId()))
                    .build();

            String questionId = String.valueOf(questions.get(questionPosition).getQuestionId());
            String questionIDSelection = AppContract.ChoiceEntry.COLUMN_QUESTION_ID + "=?";
            String[] questionIDSelectionArgs = new String[]{questionId};




            return new CursorLoader(
                    getActivity(),
                    choicesUri,
                    null,
                    questionIDSelection,
                    questionIDSelectionArgs,
                    null
            );



        }else if(id == UPDATE_CHOSEN_ANSWER_LOADER_ID){

            return new AsyncTaskLoader<Cursor>(getActivity()) {
                @Nullable
                @Override
                public Cursor loadInBackground() {

                    radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
                        @Override
                        public void onCheckedChanged(RadioGroup group, int checkedId) {

                            Uri updateChosenUri = AppContract.QuestionsEntry.CONTENT_URI
                                    .buildUpon()
                                    .appendPath(UPDATE)
                                    .appendPath(String.valueOf(questions.get(questionPosition).getQuestionId())).build();

                            ContentValues contentValues = new ContentValues();

                            contentValues.put(AppContract.QuestionsEntry.COLUMN_ANSWER_CHOSEN,checkedId);
                            if (group.getChildAt(checkedId-1).getTag().toString().equals("1")){
                                contentValues.put(AppContract.QuestionsEntry.COLUMN_IS_CHOSEN_CORRECT, 1);
                            }else if (group.getChildAt(checkedId-1).getTag().toString().equals("0")){
                                contentValues.put(AppContract.QuestionsEntry.COLUMN_IS_CHOSEN_CORRECT, 0);
                            }

                            getActivity().getContentResolver().update(updateChosenUri,contentValues,null,null);



                            Cursor cursor = getActivity().getContentResolver().query(
                                    AppContract.QuestionsEntry.CONTENT_URI.buildUpon().appendPath(String.valueOf(questions.get(questionPosition).getQuestionId())).build(),
                                    null,null,null,null
                            );

                            if (cursor.getCount() == 1){
                                cursor.moveToFirst();
                                Log.v("string", cursor.getInt(cursor.getColumnIndex(AppContract.QuestionsEntry.COLUMN_IS_CHOSEN_CORRECT))+"");
                                Log.v("string 2", group.getChildAt(radioGroup.getCheckedRadioButtonId()-1).getTag().toString());
                            }


                        }
                    });






                    return null;
                }
            };

        }

        return null;
    }

    @Override
    public void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor choicesCursor) {

        if (questionPosition == 0){
            Toast.makeText(getActivity(), ""+selectedQuiz, Toast.LENGTH_SHORT).show();
        }


        if (loader.getId() == GET_CHOICES_LOADER_ID){

            if (choicesCursor.getCount() >0){
                while (choicesCursor.moveToNext()){
                    String text = choicesCursor.getString(choicesCursor.getColumnIndex(AppContract.ChoiceEntry.COLUMN_CHOICE_TEXT));
                    int is_correct = choicesCursor.getInt(choicesCursor.getColumnIndex(AppContract.ChoiceEntry.COLUMN_IS_TRUE));

                    Choice choice = new Choice();
                    choice.setChoiceText(text);
                    choice.setCorrect(is_correct);

                    choices.add(choice);
                }

                for (int i=0; i<choices.size();i++){
                    LayoutInflater inflater = LayoutInflater.from(getContext());
                    final View radioButton = inflater.inflate(R.layout.radio_button,radioGroup,false);
                    ((RadioButton) radioButton).setText(choices.get(i).getChoiceText());
                    radioButton.setTag(choices.get(i).isCorrect());
                    radioGroup.addView(radioButton);
                }

                for (int i = 0; i<radioGroup.getChildCount();i++){
                    radioGroup.getChildAt(i).setId(i+1);
                }

            }

            if (questionPosition == 0){
                getActivity().getSupportLoaderManager()
                        .initLoader(
                                UPDATE_CHOSEN_ANSWER_LOADER_ID,
                                null,
                                this).forceLoad();
            }else {
                getActivity().getSupportLoaderManager()
                        .restartLoader(
                                UPDATE_CHOSEN_ANSWER_LOADER_ID,
                                null,
                                this).forceLoad();

            }




        }




    }

    @Override
    public void onLoaderReset(@NonNull Loader<Cursor> loader) {

    }

    public void setQuestions(ArrayList<Question> questions) {
        this.questions = questions;
    }

    public void setQuestionPosition(int questionPosition) {
        this.questionPosition = questionPosition;
    }

    public ArrayList<Question> getQuestions() {
        return questions;
    }

    public int getQuestionPosition() {
        return questionPosition;
    }

    public void setSelectedQuiz(String selectedQuiz) {
        this.selectedQuiz = selectedQuiz;
    }
}

ViewPagerAdapter

package mohalim.android.egybankstest.Adapters;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;

import java.util.ArrayList;

import mohalim.android.egybankstest.Fragments.QuizFragement;
import mohalim.android.egybankstest.Models.Question;

public class MyQuizPager extends FragmentStatePagerAdapter {
    ArrayList<Question> questions;
    String selectedQuiz;

    public MyQuizPager(FragmentManager fm, ArrayList<Question> questions, String selectedQuiz) {
        super(fm);
        this.questions = questions;
        this.selectedQuiz = selectedQuiz;
    }


    @Override
    public Fragment getItem(int position) {
        QuizFragement fragment = new QuizFragement();
        fragment.setQuestions(questions);
        fragment.setQuestionPosition(position);
        fragment.setSelectedQuiz(selectedQuiz);

        return fragment;
    }

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

    @Override
    public int getItemPosition(Object object) {
        QuizFragement fragment = (QuizFragement) object;
        int position = fragment.getQuestionPosition();

        if (position >= 0) {
            return position;
        } else {
            return POSITION_NONE;
        }
    }

}

All code is here


Solution

  • Finnaly I found the solution:

    Quate:

    By default it is viewpager.setOffscreenPageLimit(1) , meaning View pager will by default load atleast 1 on the right and one on the left tab of current tab.

    https://stackoverflow.com/a/47054077/5862361

    when i start quizActivity viewpager load the first item and the second too so the loadermanager restart before complete its work. I solved it by adding another loadermanger one for the first item and the second for the second one:

    if (questionPosition == 0){
    
                if (getActivity().getSupportLoaderManager() == null){
                    getActivity().getSupportLoaderManager().initLoader(
                            GET_CHOICES_LOADER_ID_FIRST,
                            null,
                            this
                    ).forceLoad();
                }else{
                    getActivity().getSupportLoaderManager().restartLoader(
                            GET_CHOICES_LOADER_ID_FIRST,
                            null,
                            this
                    ).forceLoad();
                }
    
    
            }else if (questionPosition == 1){
                if (getActivity().getSupportLoaderManager() == null){
                    getActivity().getSupportLoaderManager().initLoader(
                            GET_CHOICES_LOADER_ID,
                            null,
                            this
                    ).forceLoad();
                }else {
                    getActivity().getSupportLoaderManager().restartLoader(
                            GET_CHOICES_LOADER_ID,
                            null,
                            this
                    ).forceLoad();
                }
    
    
            }else {
    
                getActivity().getSupportLoaderManager().restartLoader(
                        GET_CHOICES_LOADER_ID,
                        null,
                        this
                ).forceLoad();
            }