简体   繁体   English

调用notifyDataSetChanged()时,RecyclerView不会更新或刷新

[英]RecyclerView does not update or refresh when calling notifyDataSetChanged()

IronMax app屏幕截图

I have an app that uses RecyclerView. 我有一个使用RecyclerView的应用程序。 When user selects "Add New Row" from the options menu, I output a test message to the screen, and some values get appended to two different ArrayLists. 当用户从选项菜单中选择“添加新行”时,我将测试消息输出到屏幕,并将一些值附加到两个不同的ArrayLists。 That part is working great, as I have confirmed these values are successfully added by looking at the ArrayList values using the debugger. 这部分工作得很好,因为我已经确认通过使用调试器查看ArrayList值来成功添加这些值。

Anyhow I am not able to get the RecyclerView to redraw the screen and show the new information. 无论如何,我无法让RecyclerView重绘屏幕并显示新信息。 My attempt to redraw / update the screen is by using this code (line 78 of MainActivity.java): 我尝试重绘/更新屏幕是使用此代码(MainActivity.java的第78行):

//call notify data set changed method for the adapter
  adapter.notifyDataSetChanged();

Maybe I am not calling notifyDataSetChanged on the same adapter that actually is used for RecycleView?? 也许我没有在实际用于RecycleView的同一个适配器上调用notifyDataSetChanged?

Here is the complete code for MainActivity.java (see options menu code at end): 以下是MainActivity.java的完整代码(请参阅末尾的选项菜单代码):

package com.joshbgold.ironmax;

import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private static final int ADD_ROW = 1;  //used for case statement statement to select menu item
    private RecyclerView recyclerView;
    public Exercises exercises = new Exercises();
    public ExerciseRow adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        assert getSupportActionBar() != null;
        ActionBar actionBar = getSupportActionBar();

        actionBar.setDisplayShowHomeEnabled(true);
        actionBar.setIcon(R.mipmap.barbell);
        actionBar.setTitle("  " + "Iron Max");

        recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        //ExerciseRow adapter = new ExerciseRow(this);
        adapter = new ExerciseRow(this);
        recyclerView.setAdapter(adapter);

        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);

        recyclerView.setHasFixedSize(true);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

       /* MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.add_row, menu);
        return super.onCreateOptionsMenu(menu);*/

        menu.add(0, ADD_ROW, 0, "Add New Row");
        menu.getItem(0).setIcon(R.drawable.plus);

        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        menu.getItem(0).setIcon(R.drawable.plus);

        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int length;

        switch (item.getItemId()) {
            case 1:
                Toast msg = Toast.makeText(MainActivity.this, "Test code for adding an exercise", Toast.LENGTH_LONG);
                msg.show();

                exercises.addExercise("Some exercise");
                exercises.addPersonalBest(500);
                length = exercises.getExercisesArrayLength();

               //call notify data set changed method for the adapter
                adapter.notifyItemInserted(length - 1);
                adapter.notifyDataSetChanged();

                return super.onOptionsItemSelected(item);


            default:
                return super.onOptionsItemSelected(item);
        }
    }
}

Here is Exercises.java: 这是Exercises.java:

import android.support.v7.app.AppCompatActivity;

import java.util.ArrayList;

public class Exercises extends AppCompatActivity {

    public ArrayList<String> exercisesArrayList = new ArrayList<>();  //stores all the lifts

    private ArrayList<Integer> personalBestsArrayList = new ArrayList<>();  //stores personal bests in pounds

    public ArrayList<String> getExercisesArray() {   //returns the whole exercises arraylist
        return exercisesArrayList;
    }

    public ArrayList<Integer> getPersonalBests() {  //returns the whole personal bests arraylist
        return personalBestsArrayList;
    }

    public String getExercise(int position) {  //returns individual exercise from array
        return exercisesArrayList.get(position);
    }

    public void addExercise(String exercise) {
        exercisesArrayList.add(exercise);
    }

    public void removeExercise(int position) {
        exercisesArrayList.remove(position);
    }

    public void editExercise(int position, String exercise) {
        exercisesArrayList.set(position, exercise);
    }

    public int getExercisesArrayLength() {
        return exercisesArrayList.size();
    }


    public Integer getPersonalBest(int position) {  //returns individual personal best from array
        return personalBestsArrayList.get(position);
    }

    public void addPersonalBest(int personalBest) {
        personalBestsArrayList.add(personalBest);
    }

    public void removePersonalBest(int position) {
        personalBestsArrayList.remove(position);
    }

    public void editPersonalBest(int position, int personalBest) {
        personalBestsArrayList.set(position, personalBest);
    }

    public Exercises() {} //constructor
}

Here is ExerciseRow.java: 这是ExerciseRow.java:

import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;

public class ExerciseRow extends RecyclerView.Adapter<ExerciseRow.ExerciseViewHolder> {

    String exerciseName = "burpee";
    String exercisePR = "100";  // user's personal record for this exercise in pounds

    private Context context;
    Exercises exercises = new Exercises();


    public ExerciseRow(Context context) {
        this.context = context;
    }

    @Override
    public ExerciseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.exercise_list_item, parent, false);
        return new ExerciseViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ExerciseViewHolder holder, int position) {
        ArrayList<String> exercisesArray = exercises.getExercisesArray();
        holder.bindExercises(exercisesArray.get(position));
    }

    @Override
    public int getItemCount() {
        return exercises.getExercisesArrayLength();
    }

    public class ExerciseViewHolder extends RecyclerView.ViewHolder {

        public TextView exerciseNameTextView;
        public TextView personalRecordTextView;
        public ImageView edit_Icon;
        public ImageView percentages_Icon;
        public ImageView trash_Icon;
        public ImageView plus_icon;
        public ImageView facebook_icon;
        public ImageView twitter_icon;

        public ExerciseViewHolder(View itemView) {
            super(itemView);

            exerciseNameTextView = (TextView) itemView.findViewById(R.id.list_item_exercise_textview);
            personalRecordTextView = (TextView) itemView.findViewById(R.id.list_item_amount_textview);
            edit_Icon = (ImageView) itemView.findViewById(R.id.list_item_pencil);
            percentages_Icon = (ImageView) itemView.findViewById(R.id.list_item_percent);
            trash_Icon = (ImageView) itemView.findViewById(R.id.list_item_trash);
            plus_icon = (ImageView) itemView.findViewById(R.id.list_item_plus);
            facebook_icon = (ImageView) itemView.findViewById(R.id.list_item_facebook);
            twitter_icon = (ImageView) itemView.findViewById(R.id.list_item_twitter);

            View.OnClickListener plus = new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    // allow user to add a new exercise and personal best
                    exercises.addExercise("Some exercise");
                    exercises.addPersonalBest(500);
                    notifyDataSetChanged();
                }
            };

            View.OnClickListener edit = new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    int position = getLayoutPosition();  //use getAdapterPosition() if getLayoutPosition causes a problem

                    if (position == 0) {  //prevent user from deleting the first row.
                        Toast.makeText(context, "Sorry, example row cannot be edited.", Toast.LENGTH_LONG).show();
                    }
                    else{
                        editRow(position);  //edit the row at the current position
                        notifyDataSetChanged();
                    }
                }
            };

            View.OnClickListener percentages = new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    //get exercise name
                    exerciseName = exerciseNameTextView.getText().toString();
                    exercisePR = personalRecordTextView.getText().toString();

                    //show percentages layout
                    startPercentagesActivity(exerciseName, exercisePR);
                }
            };

            View.OnClickListener trash = new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    int position = getLayoutPosition();  //use getAdapterPosition() if getLayoutPosition causes a problem

                    if (position == 0) {  //prevent user from deleting the first row.
                        Toast.makeText(context, "Sorry, example row cannot be deleted.", Toast.LENGTH_LONG).show();
                    } else {
                        exercises.removeExercise(position);
                        exercises.removePersonalBest(position);
                        notifyItemRemoved(position);
                        notifyItemRangeChanged(position, exercises.getExercisesArrayLength());
                    }
                }
            };

                plus_icon.setOnClickListener(plus);
                edit_Icon.setOnClickListener(edit);
                percentages_Icon.setOnClickListener(percentages);
                trash_Icon.setOnClickListener(trash);
            }

        public void bindExercises(String exercises) {
            Exercises exercisesObject = new Exercises();
            exerciseNameTextView.setText(exercisesObject.getExercise(getAdapterPosition()));
            personalRecordTextView.setText((exercisesObject.getPersonalBest(getAdapterPosition())).toString() + " pounds");
        }

    }

    private void startPercentagesActivity(String some_exercise, String personal_record) {
        Intent intent = new Intent(context, PercentagesActivity.class);
        intent.putExtra("exerciseName", some_exercise);
        intent.putExtra("personalRecord", personal_record);
        context.startActivity(intent);
    }

    protected void editRow(final int position) {
        LayoutInflater layoutInflater = LayoutInflater.from(context);

        //text_entry is an Layout XML file containing two text field to display in alert dialog
        final View textEntryView = layoutInflater.inflate(R.layout.text_entry, null);
        final EditText liftName = (EditText) textEntryView.findViewById(R.id.liftNameEditText);
        final EditText PersonalBestInPounds = (EditText) textEntryView.findViewById(R.id.personalBestEditText);
        final AlertDialog.Builder alert = new AlertDialog.Builder(context);

        alert.setIcon(R.mipmap.barbell)
                .setTitle("Please make your changes:")
                .setView(textEntryView)
                .setPositiveButton("Save",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int whichButton) {


                                //retrieve the user's input
                                String lift = liftName.getText().toString();
                                int personalBest = Integer.parseInt(PersonalBestInPounds.getText().toString());

                                //save the user's input to the appropriate arrays
                                exercises.editExercise(position, lift);
                                exercises.editPersonalBest(position, personalBest);
                            }
                        })
                .setNegativeButton("Cancel",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog,
                                                int whichButton) {
                            }
                        });
        alert.show();
    }
}

If you have read this far, I give you credit! 如果你已经读过这篇文章,我给你信任! Please understand I am completely new to RecyclerView, so whatever error(s) I have made could be something quite simple even. 请理解我对RecyclerView来说是全新的,所以我所做的任何错误都可能非常简单。

The issue is that you have two different instances of Exercises One in MainActivity and another in ExerciseRow You are adding the data to the wrong one. 问题是你在MainActivity有两个不同的Exercises One实例,而在ExerciseRow有另一个实例你正在将数据添加到错误的实例中。

A few other things that may help you along your way. 其他一些可能对您有所帮助的事情。

  1. Exercises Should not extend AppCompatActivity (or really anything as far as I can tell) Exercises不应该扩展AppCompatActivity (或者就我所知的任何事情而言)

  2. You should avoid saving a reference to the context (as you are doing in Exercises) it can great memory issues. 你应该避免保存对上下文的引用(正如你在练习中所做的那样)它可能会产生很大的内存问题。 Instead try one of the following. 而是尝试以下之一。

    A. Use the context to get the LayoutInflater in the constructor A.使用上下文在构造函数中获取LayoutInflater

    B. Call parent.getContext() in onCreateViewHolder B.在onCreateViewHolder调用parent.getContext()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 NotifyDataSetChanged无法正确更新RecyclerView - NotifyDataSetChanged does not update the RecyclerView correctly 从BaseAdapter调用notifyDataSetChanged时,ListView不会更新 - ListView does not update when calling notifyDataSetChanged from a BaseAdapter 为什么在没有notifyDataSetChanged()的情况下更新RecyclerView? - Why Does RecyclerView Update Without notifyDataSetChanged()? notifyDataSetChanged 方法不更新 RecyclerView 布局 - The notifyDataSetChanged method does no update the RecyclerView layout 调用notifydatasetchanged()时,FragmentStatePageAdapter不会刷新 - FragmentStatePageAdapter won't refresh when calling notifydatasetchanged() 使用 RecyclerView 时,notifydatasetchanged 是否调用 onCreateViewHolder - Does notifydatasetchanged call onCreateViewHolder when using RecyclerView 如何更新RecyclerView-notifyDataSetChanged() - How to Update RecyclerView - notifyDataSetChanged() notifyDataSetChanged不刷新RecyclerView - notifyDataSetChanged doesn't refresh RecyclerView 在notifydatasetchanged()之后,RecyclerView不会更新onBindViewHolder中的私有字段 - RecyclerView does not update a private field in onBindViewHolder after notifydatasetchanged() RecyclerView中的notifyDataSetChanged时如何使指定的项目不更新 - How to make specified item not update when notifyDataSetChanged in RecyclerView
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM