[英]RecyclerView does not update or refresh when calling notifyDataSetChanged()
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. 其他一些可能对您有所帮助的事情。
Exercises
Should not extend AppCompatActivity
(or really anything as far as I can tell) Exercises
不应该扩展AppCompatActivity
(或者就我所知的任何事情而言)
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.