我将难以解释这里的问题,但我会尝试。
所以我有一个ViewPager
,其中包含很多Fragment
,由FragmentStatePagerAdapter
管理,这些Fragment
是与抽象类{{1}相关的卡片}有多个孩子Question
,TrueFalseQuestion
等。但只有MultipleChoiceQuestion
的{{1}}类型Fragment
:
QuestionFragment
所以我必须保存用户的输入和服务器在onSaveInstanceState上发送的答案,以便在配置更改时正确重建。
但是当我改变方向时,我放松了用户输入。
您会找到一个名为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();
}
}
的方法,我创建该方法以查看问题所在。我在viewPager更改其页面时调用它,似乎我总是得到这些日志:
public void logTest()
并且片段的Id与onCreate中的ID不同:
E/ID: QuestionFragment{edb2fad}
holder is nothing!
holder ==null ?true
(holder instanceof QuestionViewHolder) ?false
所以我认为我有两倍的片段而且显示了错误的片段,但在我的Activity onCreate中我测试了我有多少片段:
/ID: QuestionFragment{68fc4ae #1 id=0x7f0e00a5}
似乎我的数量很多。所以我创建Fragments Every Logs表示他们有更正用户输入,我将它们逐个添加到我的适配器,其中只包含其中的那些,但当我切换页面时,并调用它:
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();
}
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() {
}
}
谢谢,