RecyclerView не восстанавливается при изменении ориентации - PullRequest
0 голосов
/ 19 мая 2018

Я пытаюсь настроить приложение на изменение ориентации.Сейчас я работаю с RecyclerView, у которого есть CustomAdapter для обработки данных.Я реализовал onSaveInstanceState для сохранения данных, находящихся в Adapter, но когда я вставляю их заново после изменения ориентации, метод onBindViewHolder не вызывается.Я подтвердил, что данные сохранены, а списки массивов не пусты и содержат нужные мне данные.

Вот код CustomAdapter:

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {
    private static final String TAG = "CustomAdapter";

    private  ArrayList<Words> mDataSet;
    private  RecyclerView mRecyclerView;
    private  PopupWindow mPopupWindow;
    private  int currentPos;
    private  String srcOld;
    private  String targetOld;
    private  TranslateActivityFragment mFragment;
    private  EditText mEditSrc;
    private  EditText mEditTarget;

    public class ViewHolder extends RecyclerView.ViewHolder {
        private TextView textView;
        private TextView textView2;
        private TextView textView3;

        public ViewHolder(View v){
            super(v);
            textView =  v.findViewById(R.id.adapter_textview1);
            textView2 = v.findViewById(R.id.adapter_textview2);
            textView3 = v.findViewById(R.id.adapter_textview3);
            v.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v){
                    mPopupWindow.showAtLocation(mRecyclerView, Gravity.CENTER,0,0);
                    mPopupWindow.setFocusable(true);
                    mPopupWindow.update();
                    currentPos = getAdapterPosition();
                    setCurrText();
                }
                private void setCurrText(){
                    Words tmp = mDataSet.get(currentPos);
                    srcOld = tmp.getW1();
                    targetOld = tmp.getW2();
                    mEditSrc.setText(srcOld);
                    mEditTarget.setText(targetOld);
                }
            });
        }

        public TextView getLeftTextView(){
            return textView;
        }
        public TextView getCenterTextView(){return textView2;}
        public TextView getRightTextView(){return textView3;}

    }

    public CustomAdapter(RecyclerView recyclerView, Context context, TranslateActivityFragment fragment){
        mRecyclerView = recyclerView;
        mDataSet = new ArrayList<Words>();
        mFragment = fragment;
        this.notifyDataSetChanged();
        View v = LayoutInflater.from(mFragment.getActivity()).inflate(R.layout.edit_translate,null,false);
        createPopupWindow(v, mFragment.getActivity());
        setEditText(v);
    }
    private void setEditText(View v){
        mEditSrc = v.findViewById(R.id.edit_src);
        mEditTarget = v.findViewById(R.id.edit_target);
    }

    private void createPopupWindow(View v, Activity activity){
        DisplayMetrics metrics = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
        float width = 300*metrics.density;
        float height = 200*metrics.density;
        mPopupWindow = new PopupWindow(v,(int)width, (int)height);
        Button buttonOk = v.findViewById(R.id.button_ok);
        Button buttonCancel = v.findViewById(R.id.button_cancel);
        Button buttonDelete = v.findViewById(R.id.button_delete);

        buttonCancel.setOnClickListener(new CancelListener());
        buttonOk.setOnClickListener(new OkListener());
        buttonDelete.setOnClickListener(new DeleteListener());
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType){
        View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.textview_layout, viewGroup,false);
        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, final int position){
        Log.d(TAG, "Element " + position + " set." + mDataSet.get(position).getW1());
        viewHolder.getLeftTextView().setText(mDataSet.get(position).getW1());
        viewHolder.getCenterTextView().setText(" - ");
        viewHolder.getRightTextView().setText( mDataSet.get(position).getW2());

    }

    @Override
    public int getItemCount() {
        return mDataSet.size();
    }

    public void addData(Words newData, RecyclerView recyclerView){
        mDataSet.add(newData);
        System.out.println("------ ADDING DATA--------");
        this.notifyDataSetChanged();
        if (mDataSet.size() > 0) {
            recyclerView.smoothScrollToPosition(mDataSet.size() - 1);
        }
    }

    public void dismissPopup(){
        mPopupWindow.dismiss();
    }

    public void removeWord(){
        mDataSet.remove(currentPos);
        System.out.println("mDataSet.size(): " + mDataSet.size());
        System.out.println("mFragment.getTranslater.getData.size(): " + mFragment.getTranslater().getWords().size());
        mFragment.getTranslater().deleteWord(currentPos);
        this.notifyDataSetChanged();
    }

    // Update the current word from EditTexts
    public void updateWord(){
        String src = mEditSrc.getText().toString();
        String target = mEditTarget.getText().toString();
        mDataSet.get(currentPos).setW1(src);
        mDataSet.get(currentPos).setW2(target);
        mFragment.getTranslater().updateWord(src, target, currentPos);
        this.notifyDataSetChanged();
    }
    private class OkListener implements View.OnClickListener {

        @Override
        public void onClick(View view) {
            updateWord();
            dismissPopup();
        }
    }

    private class CancelListener implements View.OnClickListener{
        @Override
        public void onClick(View view){
            dismissPopup();
        }
    }
    private class DeleteListener implements View.OnClickListener{
        @Override
        public void onClick(View view){
            removeWord();
            dismissPopup();

        }
    }

    public ArrayList<Words> getWords(){
        return mDataSet;
    }

    public ArrayList<String> getW1List() {
        ArrayList<String> tmp = new ArrayList<>();
        for (Words w : mDataSet){
            tmp.add(w.getW1());
        }
        return tmp;
    }

    public ArrayList<String> getW2List(){
        ArrayList<String> tmp = new ArrayList<>();
        for (Words w : mDataSet){
            tmp.add(w.getW2());
        }
        return tmp;
    }
    //
    // Here is where I try to restore data.
    //
    public void restoreWords(ArrayList<String> w1, ArrayList<String> w2, RecyclerView recyclerView){
        if (mDataSet == null){
            mDataSet = new ArrayList<>();
        }
        System.out.println("Restoring words");
        for (int i = 0; i < w1.size(); ++i){
            Words tmp = new Words(w1.get(i), w2.get(i), 0,0,0,false);
            addData(tmp, recyclerView);
        }
    }
}

Код в Fragment для обработкипредставление:

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mAdapter = new CustomAdapter(mRecyclerView, this.getContext(), this);
        mRecyclerView.setAdapter(mAdapter);

        if (savedInstanceState != null){

            ArrayList<String> w1 = savedInstanceState.getStringArrayList(TranslateActivity.W1LIST);
            ArrayList<String> w2 = savedInstanceState.getStringArrayList(W2LIST);
            restoreWords(w1,w2);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.fragment_translate, container, false);
        mRecyclerView = root.findViewById(R.id.translate_recycle);
        mLayoutManager = new LinearLayoutManager(getActivity(), LinearLayout.VERTICAL, false);
        mRecyclerView.setLayoutManager(mLayoutManager);
        return root;
    }

    @Override
    public void onViewCreated(View v, Bundle savedInstanceState){
        mHelper = new Helper();

        if (savedInstanceState == null) {

            Intent intent = getActivity().getIntent();
            source_lang = intent.getStringExtra(MainActivityFragment.SOURCE_LANG);
            target_lang = intent.getStringExtra(MainActivityFragment.TARGET_LANG);
        } else {
            source_lang = savedInstanceState.getString(MainActivityFragment.SOURCE_LANG);
            target_lang = savedInstanceState.getString(MainActivityFragment.TARGET_LANG);
        }
        key = mHelper.getKey(source_lang, target_lang);
        mTranslater = new Translater(source_lang, target_lang, key);
        setHasOptionsMenu(true);

        setToolbarText();
    }

    public void restoreWords(ArrayList<String> w1, ArrayList<String> w2){
        System.out.println("..................RESTORE WORDS....................");
        mAdapter.restoreWords(w1, w2, mRecyclerView);
    }

onCreate в Деятельности:

  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        helper = new Helper();
        mInAppPurchase = new InAppPurchase(this, this);
        mInAppPurchase.setUpNoQuery();
        setContentView(R.layout.activity_translate);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        mFragment = new TranslateActivityFragment();

        View v = LayoutInflater.from(getApplicationContext()).inflate(R.layout.start_purchase_ui, null, false);
        createPopup(v, this);

           getSupportFragmentManager().beginTransaction().replace(R.id.translate_layout, mFragment).commit();
    }

Я посмотрел вокруг и увидел несколько предложений изменить getItemCount, чтобы не возвращать 0.Это не помогло, и я не очень понимаю, как это может быть проблемой. Здесь здесь говорится, что для ListViews необходимо выполнить восстановление в onCreateView или onActivityCreated, что тоже не помогло.

Обратите внимание, что notifyDataSetChanged вызывается в addData(Words word)

РЕДАКТИРОВАТЬ: я изменил поток на следующее:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View root = inflater.inflate(R.layout.fragment_translate, container, false);
    mRecyclerView = root.findViewById(R.id.translate_recycle);
    mLayoutManager = new LinearLayoutManager(getActivity(), LinearLayout.VERTICAL, false);
    mRecyclerView.setLayoutManager(mLayoutManager);
    mAdapter = new CustomAdapter(mRecyclerView, this.getContext(), this);
    mRecyclerView.setAdapter(mAdapter);
    return root;
}

@Override
public void onViewCreated(View v, Bundle savedInstanceState){
    mHelper = new Helper();

    if (savedInstanceState == null) {
        // Create helper instance
        // Get the input view from which we get the source word
        textInput = v.findViewById(R.id.source_input);
        // Extract the chosen langauges
        Intent intent = getActivity().getIntent();
        source_lang = intent.getStringExtra(MainActivityFragment.SOURCE_LANG);
        target_lang = intent.getStringExtra(MainActivityFragment.TARGET_LANG);
    } else {
        source_lang = savedInstanceState.getString(MainActivityFragment.SOURCE_LANG);
        target_lang = savedInstanceState.getString(MainActivityFragment.TARGET_LANG);
        ArrayList<String> w1 = savedInstanceState.getStringArrayList(TranslateActivity.W1LIST);
        ArrayList<String> w2 = savedInstanceState.getStringArrayList(W2LIST);
        restoreWords(w1,w2);

    }
    key = mHelper.getKey(source_lang, target_lang);
    mTranslater = new Translater(source_lang, target_lang, key);
    setHasOptionsMenu(true);
    setToolbarText();
}

Дополнительная информация:

У меня есть элемент EditText, из которого я читаю ввод идобавить к mAdapter.После вращения это все еще работает.Это только когда я пытаюсь повторно вставить сохраненные данные, это не работает.Так что я подозреваю, что restoreWords вызваны не с того метода?

1 Ответ

0 голосов
/ 19 мая 2018

Таким образом, похоже, что решение было сделать восстановление в Activity вместо Fragment.Я сделал почти так же, как в моем вопросе.Я переписал onRestoreInstanceState и назвал restoreWords реализованным как

public void restoreWords(ArrayList<String> w1, ArrayList<String> w2){
    System.out.println("..................RESTORE WORDS....................");
    for (int i = 0; i < w1.size(); ++i){
        Words tmp = new Words(w1.get(i), w2.get(i), 0, 0, 0, false);
        System.out.println(tmp.getW1() + "   ---   " + tmp.getW2());
        mFragment.addWordToView(tmp);
    }
    System.out.println("-------------------Number of words in adapter: " + mFragment.getAdapter().getItemCount());
}

Тогда это волшебным образом сработало.Может кто-нибудь объяснить, почему?

...