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

时间:2016-05-25 22:25:45

标签: android android-recyclerview

IronMax app screen capture

我有一个使用RecyclerView的应用。当用户从选项菜单中选择“添加新行”时,我将测试消息输出到屏幕,并将一些值附加到两个不同的ArrayLists。这部分工作得很好,因为我已经确认通过使用调试器查看ArrayList值来成功添加这些值。

无论如何,我无法让RecyclerView重绘屏幕并显示新信息。我尝试重绘/更新屏幕是使用此代码(MainActivity.java的第78行):

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

也许我没有在实际用于RecycleView的同一个适配器上调用notifyDataSetChanged?

以下是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);
        }
    }
}

这是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
}

这是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();
    }
}

如果您已经读过这篇文章,我会给您信任!请理解我对RecyclerView来说是全新的,所以我所做的任何错误都可能非常简单。

1 个答案:

答案 0 :(得分:0)

问题在于Exercises中有MainActivity一个ExerciseRow而另一个Exercises中存在另一个实例。您正在将数据添加到错误的实例中。

其他一些可能对您有所帮助的事情。

  1. AppCompatActivity不应该延伸parent.getContext()(或者我可以告诉的任何事情)

  2. 您应该避免保存对上下文的引用(正如您在练习中所做的那样),这会导致很大的内存问题。而是尝试以下之一。

    一个。使用上下文在构造函数中获取LayoutInflater

    B中。在onCreateViewHolder

  3. 中致电textField.add( new EmptyBorder(...) );