Android 在ViewPager中恢复片段状态时出现的问题(使用FragmentStatePagerAdapter)

Android 在ViewPager中恢复片段状态时出现的问题(使用FragmentStatePagerAdapter),android,android-fragments,android-viewpager,fragmentpageradapter,Android,Android Fragments,Android Viewpager,Fragmentpageradapter,我很难解释这里的问题是什么,但我会努力的 因此,我有一个ViewPager,里面有很多Fragment,由FragmentStatePagerAdapter管理,这些Fragment是与一个抽象类Question相关的卡片,这个抽象类有多个孩子TrueFalseQuestion,多个回音问题等等。。但只有一种类型的片段,即问题片段: public class QuestionFragment extends ElementFragment { public static String

我很难解释这里的问题是什么,但我会努力的

因此,我有一个
ViewPager
,里面有很多
Fragment
,由
FragmentStatePagerAdapter
管理,这些
Fragment
是与一个抽象类
Question
相关的卡片,这个抽象类有多个孩子
TrueFalseQuestion
多个回音问题
等等。。但只有一种类型的
片段
,即
问题片段

public class QuestionFragment extends ElementFragment {

    public static String ARG_DATA = "c0pcjOLtwAoIMDe1lwJ4";
    protected static String ARG_SOURCE = "source";
    protected static String ARG_ANWSER_CORRECTION = "LPYmZpVmnhssq762mLpu";
    protected static String ARG_COURSE_MODE = "COURSEMODE";

    protected ElementViewerActivity.Source source;


    protected Question mQuestion;
    protected QuestionType mQtype;

    protected CollectedAnswers userAnswer;
    protected QuestionAnswerResponse serverResponse;

    protected QuestionViewHolder holder;

    private CourseMode mCourseMode;



    /*Lot of different newInstance here, I don't think they are relevant*/

    public QuestionFragment() {
        // Required empty public constructor
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        //Log.i("renaud", "savingInstanceState : userAnswer==null?:" + (userAnswer == null) + " | serverResponse==null?:" + (serverResponse == null));
        outState.putSerializable("userAnswer", userAnswer);
        outState.putSerializable("serverResponse", serverResponse);
        Log.i("renaud","question fragment state saved");
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        mQuestion = (Question) getArguments().get(ARG_DATA);
        Log.e("ID ",this.toString());

        setRetainInstance(true);

        source = (ElementViewerActivity.Source) getArguments().get(ARG_SOURCE);
        mCourseMode = (CourseMode) getArguments().get(ARG_COURSE_MODE);

        QuestionAnswerCorrection questionAnswerCorrection = (QuestionAnswerCorrection) getArguments().get(ARG_ANWSER_CORRECTION);
        if(questionAnswerCorrection!= null && savedInstanceState==null){
            userAnswer = questionAnswerCorrection.userAnswer;
            serverResponse = questionAnswerCorrection.serverResponse;
        }

        mQtype = mQuestion.getQtype();

        Activity activity = getActivity();

        switch (mQtype) {
            case TRUE_FALSE:
                holder = new QuestionTFViewHolder(activity, mQuestion);
                Log.e("DEBUG --TF-- ","holder = new QuestionTFViewHolder(activity, mQuestion)");
                break;
            case MULTIPLE_CHOICES:
                holder = new QuestionMCViewHolder(activity, mQuestion);
                Log.e("DEBUG --MC-- ","holder = new QuestionMCViewHolder(activity, mQuestion)");
                break;
            case ORDER:
                holder = new QuestionOrderViewHolder(activity, mQuestion);
                break;
            case LINKER:
                holder = new QuestionLinkerViewHolder(activity, mQuestion);
                break;
            case OPEN:
                holder = new QuestionOpenViewHolder(activity, mQuestion);
                break;
            case AREA:
                holder = new QuestionAreaViewHolder(activity, mQuestion);
                break;
            default:
                Log.e("renaud", "Question non traitée " + mQtype);
                break;
        }
        // Inflate the layout for this fragment
        if (savedInstanceState != null) {

            Log.i("renaud","restore onCreateView :"+mQtype.name());

            Serializable serializedUserAnswer = savedInstanceState.getSerializable("userAnswer");

            if(serializedUserAnswer instanceof BooleanCollectedAnswer){
                userAnswer = (BooleanCollectedAnswer) serializedUserAnswer;
                Log.e("renaud","serializedUserAnswer instanceof BooleanCollectedAnswer");
            } else if(serializedUserAnswer instanceof CoordinateCollectedAnswer) {
                userAnswer = (CoordinateCollectedAnswer) serializedUserAnswer;
                Log.e("renaud","serializedUserAnswer instanceof CoordinateCollectedAnswer");
            } else if (serializedUserAnswer instanceof IntegerListCollectedAnswer) {
                userAnswer = (IntegerListCollectedAnswer) serializedUserAnswer;
                Log.e("renaud","serializedUserAnswer instanceof IntegerListCollectedAnswer");
            } else if (serializedUserAnswer instanceof OpenCollectedAnswer) {
                userAnswer = (OpenCollectedAnswer) serializedUserAnswer;
                Log.e("renaud","serializedUserAnswer instanceof OpenCollectedAnswer");
            }else{
                Log.e("renaud","bug");
            }
            //userAnswer = (CollectedAnswers) savedInstanceState.getSerializable("userAnswer");
            serverResponse = (QuestionAnswerResponse) savedInstanceState.getSerializable("serverResponse");
            Log.i("renaud", "Question fragment SAVED INSTANCE STATE NOT NULL (userAnswer==null)=" + (userAnswer == null) + " | (serverResponse==null):" + (serverResponse == null));
        }

        View v = null;
        switch (mQtype) {
            case TRUE_FALSE:
                v = inflater.inflate(R.layout.fragment_question_container, container, false);
                break;
            case MULTIPLE_CHOICES:
                v = inflater.inflate(R.layout.fragment_question_container, container, false);
                break;
            case ORDER:
                v = inflater.inflate(R.layout.fragment_question_container, container, false);
                break;
            case LINKER:
                v = inflater.inflate(R.layout.fragment_question_container, container, false);
                break;
            case OPEN:
                v = inflater.inflate(R.layout.fragment_question_container, container, false);
                break;
            case AREA:
                v = inflater.inflate(R.layout.fragment_question_container, container, false);
            default:
                Log.e("renaud", "Question non traitée " + mQtype);
                break;
        }

        holder.initWithView(v, new SendResponseOnClicListener());
        //Quand une question est vue dans l'elementViewer, cad lancé depuis le news feed, on ne peut pas envoyer la réponse.
        if (source == ElementViewerActivity.Source.VIEWER) {
            holder.sendAnswer.setVisibility(View.GONE);
        }
        if (serverResponse != null || userAnswer != null) {
            //Log.i("renaud", "server response != null ? " + (serverResponse != null));
            //Log.i("renaud", "userAnswer != null ? " + (userAnswer != null));

            Log.i("renaud","savedInstanceState != null, (userAnswer!=null):"+(userAnswer!=null));

            holder.setCollectedAnswers(userAnswer);
            holder.answerSentSetDisable();
            if(mCourseMode !=null && mCourseMode == CourseMode.TRAINING) {
                holder.fillCorrection(serverResponse);
            }

            /*if(holder instanceof QuestionMCViewHolder){
                QuestionMCViewHolder mcViewHolder = (QuestionMCViewHolder) holder;
                for(int i = 0; i< mcViewHolder.mcLayout.getChildCount();i++){
                    Log.i("Renaud","test dans question fragment :"+((CheckBox) mcViewHolder.mcLayout.getChildAt(i)).isChecked());
                }
            }*/

        }

        return v;
    }

    public void logTest(){

        if(holder instanceof QuestionMCViewHolder){
            Log.i("renaud","it's a question mc view holder");
            QuestionMCViewHolder mcViewHolder = (QuestionMCViewHolder) holder;
            for(int i = 0; i< mcViewHolder.mcLayout.getChildCount();i++){
                Log.i("Renaud","test dans question fragment :"+((CheckBox) mcViewHolder.mcLayout.getChildAt(i)).isChecked());
            }
        } else if(holder instanceof QuestionOrderViewHolder) {
            Log.i("renaud","it's a QuestionOrderViewHolder");
        } else if (holder instanceof QuestionLinkerViewHolder) {
            Log.i("renaud","it's a QuestionLinkerViewHolder");
        } else if (holder instanceof QuestionTFViewHolder) {
            Log.i("renaud","it's a QuestionTFViewHolder");
        } else if (holder instanceof QuestionOpenViewHolder) {
            Log.i("renaud","it's a QuestionOpenViewHolder");
        } else if (holder instanceof QuestionAreaViewHolder) {
            Log.i("renaud","it's a QuestionAreaViewHolder");
        }else{
            Log.e("ID ",this.toString());
            Log.i("renaud","holder is nothing!");
            Log.i("renaud","holder ==null ?"+(holder==null));
            Log.i("renaud","(holder instanceof QuestionViewHolder) ?"+(holder instanceof QuestionViewHolder));

        }
    }


    public class SendResponseOnClicListener implements View.OnClickListener {
        @Override
        public void onClick(final View v) {

            holder.answerSentSetDisable();


            //TODO ARE ALL DOCUMENTS UPLOADED WHEN IT'S AN OPEN QUESTION ?

            //final QuestionOpenViewHolder openHolder = (QuestionOpenViewHolder) holder;
            userAnswer = holder.collectAnswer();


            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        final QuestionAnswerResponse response =
                                CourseRepository.getInstance().postQuestionAnswer(mQuestion.getId(), mQuestion.getCreatedFor(), userAnswer);

                        EventBus.getDefault().post(new EnableNextEvent(mQuestion.getId()));

                        getActivity().runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                serverResponse = response;
                                if(mCourseMode !=null && mCourseMode == CourseMode.TRAINING) {
                                    holder.fillCorrection(serverResponse);
                                }
                                //holder.fillCorrection(response);
                            }
                        });
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();


        }
    }

    public class AnswerCollectedEvent {
        public CollectedAnswers userAnswer;
        public QuestionAnswerResponse serverResponse;
        public String questionId;

        public AnswerCollectedEvent(String questionId, CollectedAnswers userAnswer, QuestionAnswerResponse serverResponse) {
            this.userAnswer = userAnswer;
            this.questionId = questionId;
            this.serverResponse = serverResponse;
        }
    }

    public static class EnableNextEvent {

        public String id;

        public EnableNextEvent(String id) {
            this.id = id;
        }


    }

    @Override
    public void onStop() {
        //EventBus.getDefault().unregister(this);
        super.onStop();
    }

    @Override
    public void onStart() {
        //EventBus.getDefault().register(this);
        super.onStart();
    }


}
片段的Id与onCreate中的Id不同,如下所示:

/ID: QuestionFragment{68fc4ae #1 id=0x7f0e00a5}
因此,我认为我有两个片段,并且显示了错误的片段,但在我的创建活动中,我测试了我有多少片段:

mPagerAdapter.addItem(QuestionFragment.newInstance(question, ElementViewerActivity.Source.PLAYER, mCourseMode));
Log.e("renaud", "restore count mPagerAdapter : " + mPagerAdapter.getFragmentResgisteredCount());
看来我有很多钱。所以我创建了片段,每个日志都表明它们有正确的用户输入,我将它们一个一个地添加到我的适配器中,该适配器表示其中只有一个,但当我切换页面时,调用:

Log.i("renaud","page selected "+position);
Fragment fragment = mPagerAdapter.getItem(position);
if(fragment instanceof QuestionFragment){
   Log.i("renaud","it's a question fragment");
   ((QuestionFragment) fragment).logTest();
}
日志测试被调用,但根据我上面给出的结果

---编辑---

公共类QuestionMCViewHolder扩展了QuestionViewHolder{
公共线路布局;
公共问题MCViewHolder(活动,问题){
超级(活动、问题);
}
私人充气机;
@凌驾
public void initWithView(视图v,QuestionFragment.SendResponseOnClicListener onClicListener){
Log.i(“雷诺”,“问题视图持有人initWithView”);
super.initWithView(v,onClicListener);
充气机=从(mActivity)开始的充气机;
container.addView(充气器.充气(R.layout.fragment_question_container_mc,null));
mcLayout=(线性布局)v.findviewbyd(R.id.mc_布局);
for(字符串文本:question.getAnswers()){
复选框cb=(复选框)充气器。充气(R.layout.fragment\u question\u container\u mc\u item,null);
cb.setText(文本);
cb.setChecked(假);
mcLayout.addView(cb);
}
}
@凌驾
公开更正(问题解答回答){
super.fillCorrection(答案);
视图v=充气机。充气(R.layout.fragment\u question\u container\u mc,空);
LinearLayout answerLayout=(LinearLayout)v.findViewById(R.id.mc_布局);
for(整数位置:answer.getAnswers()){
复选框cb=(复选框)充气器。充气(R.layout.fragment\u question\u container\u mc\u item,null);
cb.setText(question.getAnswers().get(position));
cb.setChecked(真);
cb.setEnabled(假);
//cb.挫折背景资源(R.color.question_true);
回答布局。添加视图(cb);
}
修正规格容器。添加视图(v);
AnimationUtils.expand(correctionLayout);
}
@凌驾
公共整数ListCollectedAnswer collectAnswer(){
IntegerListCollectedAnswer answer=新IntegerListCollectedAnswer();
对于(int i=0;i

公共类IntegerListCollectedAnswer扩展CollectedAnswers{
public ArrayList list=new ArrayList();
公共整数列表CollectedAnswer(ArrayList列表){
this.list=列表;
}
公共整数ListCollectedAnswer(){
}
}

公共类PlayerPageAdapter扩展了FragmentStatePagerAdapter{
//专用SparseArray registeredFragments=新SparseArray();
私有ArrayList registeredFragments=新ArrayList();
/*公共无效恢复标签(ArrayList registeredFragments,内部位置){
this.registeredFragments=registeredFragments;
notifyDataSetChanged();
切换到项目(位置);
}*/
public int getFragmentResRegisteredCount(){
返回registeredFragments.size();
}
公共播放器管理器适配器(FragmentManager fm){
超级(fm);
}
@凌驾
public int getCount(){
返回Math.min(registeredFragments.size(),mMaxIndexQuestionAllowed+1);
}
公共无效附加项(ElementFragment ElementFragment){
add(elementFragment);
}
@凌驾
公共片段getItem(int位置){
返回registeredFragments.get(位置);
}
}

谢谢,

你能给我看看你的FragmenStatePagerAdapter课程吗?最重要的方法是getItem和InstanceItem。您可以显示FragmenStatePagerAdapter类吗?最重要的方法是getItem和instanceItem
Log.i("renaud","page selected "+position);
Fragment fragment = mPagerAdapter.getItem(position);
if(fragment instanceof QuestionFragment){
   Log.i("renaud","it's a question fragment");
   ((QuestionFragment) fragment).logTest();
}
public class QuestionMCViewHolder extends QuestionViewHolder {

    public LinearLayout mcLayout;

    public QuestionMCViewHolder(Activity activity, Question question) {
        super(activity, question);
    }

    private LayoutInflater inflater;

    @Override
    public void initWithView(View v, QuestionFragment.SendResponseOnClicListener onClicListener) {

        Log.i("renaud","QuestionMCViewHolder initWithView");

        super.initWithView(v, onClicListener);

        inflater = LayoutInflater.from(mActivity);
        container.addView(inflater.inflate(R.layout.fragment_question_container_mc, null));
        mcLayout = (LinearLayout) v.findViewById(R.id.mc_layout);

        for (String text : question.getAnswers()) {
            CheckBox cb = (CheckBox) inflater.inflate(R.layout.fragment_question_container_mc_item, null);
            cb.setText(text);
            cb.setChecked(false);
            mcLayout.addView(cb);
        }


    }


    @Override
    public void fillCorrection(QuestionAnswerResponse answer) {
        super.fillCorrection(answer);


        View v = inflater.inflate(R.layout.fragment_question_container_mc, null);
        LinearLayout answerLayout = (LinearLayout) v.findViewById(R.id.mc_layout);


        for (Integer position : answer.getAnswers()) {
            CheckBox cb = (CheckBox) inflater.inflate(R.layout.fragment_question_container_mc_item, null);


            cb.setText(question.getAnswers().get(position));
            cb.setChecked(true);
            cb.setEnabled(false);
            //cb.setBackgroundResource(R.color.question_true);
            answerLayout.addView(cb);
        }
        correctionSpecificContainer.addView(v);

        AnimationUtils.expand(correctionLayout);
    }

    @Override
    public IntegerListCollectedAnswer collectAnswer() {

        IntegerListCollectedAnswer answer = new IntegerListCollectedAnswer();
        for (int i = 0; i < mcLayout.getChildCount(); i++) {
            if (((CheckBox) mcLayout.getChildAt(i)).isChecked()) {
                answer.list.add(i);
            }
        }
        return answer;
    }

    @Override
    public void setCollectedAnswers(CollectedAnswers answers) {

        Log.w("renaud","QuestionMCViewHolder setCollectedAnswers");

        if (answers instanceof IntegerListCollectedAnswer) {
            IntegerListCollectedAnswer integers = (IntegerListCollectedAnswer) answers;

            //mcLayout.removeAllViews();

            for (int i = 0; i < question.getAnswers().size(); i++) {
                CheckBox cb = (CheckBox) mcLayout.getChildAt(i);  //inflater.inflate(R.layout.fragment_question_container_mc_item, null);
                //cb.setText(question.getAnswers().get(i));
                //Log.i("QUESTIONMC SETCOLLECTED", "integers.list.contains(i) = " + integers.list.contains(i));

                //mcLayout.addView(cb);
                cb.setChecked(integers.list.contains(i));
                Log.d("renaud", "setCollectedAnswers cb.isChecked():"+cb.isChecked());
            }



        } else {
            Log.i("renaud", "CollectedAnswers instanceof IntegerListCollectedAnswer failed");
        }


    }
}
public class IntegerListCollectedAnswer extends CollectedAnswers {
    public ArrayList<Integer> list = new ArrayList<>();

    public IntegerListCollectedAnswer(ArrayList<Integer> list) {
        this.list = list;
    }

    public IntegerListCollectedAnswer() {
    }
}
public class PlayerPagerAdapter extends FragmentStatePagerAdapter {

        //private SparseArray<ElementFragment> registeredFragments = new SparseArray<>();
        private ArrayList<ElementFragment> registeredFragments = new ArrayList<>();


        /*public void restoreFragment(ArrayList<ElementFragment> registeredFragments, int position) {
            this.registeredFragments = registeredFragments;
            notifyDataSetChanged();
            switchToItem(position);
        }*/

        public int getFragmentResgisteredCount(){
            return registeredFragments.size();
        }

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

        @Override
        public int getCount() {
            return Math.min(registeredFragments.size(),mMaxIndexQuestionAllowed + 1);
        }

        public void addItem(ElementFragment elementFragment) {
            registeredFragments.add(elementFragment);
        }


        @Override
        public Fragment getItem(int position) {
            return registeredFragments.get(position);
        }


    }