从中删除项目后 ListView 不“刷新”

Posted

技术标签:

【中文标题】从中删除项目后 ListView 不“刷新”【英文标题】:ListView not "refreshing" after item is deleted from it 【发布时间】:2015-10-18 17:17:50 【问题描述】:

我试图弄清楚当我的列表视图中的项目被删除时,我如何“刷新”用户所在的列表视图。我尝试了 notifyDataSetChanged() 但无济于事,这让我感到困惑,因为这在我添加项目时有效。

附:我知道该项目将被删除,因为如果我按下后退按钮并再次进入我的活动,则该项目会从列表视图中直观地删除。

    public void deleteButtonClicked(View view)
    dbHandler.deleteExerciseFromDatabase(exerciseClickedbyUser, workoutClicked);
    exerciseListView.setAdapter(edsAdapter);
    edsAdapter.notifyDataSetChanged();
    Toast.makeText(getBaseContext(),"Exercise Deleted", Toast.LENGTH_SHORT).show();


当我在模拟器中运行它时,Toast 确实出现了。

公共类 CustomExerciseAdapter 扩展 ArrayAdapter

public CustomExerciseAdapter(Context context, ArrayList<String> workouts) 
    super(context, R.layout.exercise_custom_row, workouts);


@Override
public View getView(int position, View convertView, ViewGroup parent) 
    LayoutInflater inflater = LayoutInflater.from(getContext());
    View customView = inflater.inflate(R.layout.exercise_custom_row, parent, false);

    String singleExerciseItem = getItem(position);
    TextView exerciseTV = (TextView) customView.findViewById(R.id.exerciseTV);
    exerciseTV.setText(singleExerciseItem);

    return customView;

这是我的包含 deleteButtonClicked 的类

public class ExercisesSection extends ActionBarActivity 

private EditText userWorkoutInput;
private Button addNewWorkoutButton;
private CustomExerciseAdapter edsAdapter;
private ArrayList<String> itemHold;
private MyDBHandler dbHandler;
private String workoutClicked;
private String exerciseClickedbyUser;
private ListView exerciseListView;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    getSupportActionBar().hide();
    setContentView(R.layout.activity_exercises_section);

    initViews();
    handleIntentData();
    inputTextHandler();
    loadDataFromDatabase();



//This method initializes all the views
public void initViews()
    userWorkoutInput = (EditText) findViewById(R.id.userWorkoutInput);
    addNewWorkoutButton = (Button) findViewById(R.id.addNewWorkoutButton);
    exerciseListView = (ListView) findViewById(R.id.exerciseListView);
    itemHold = new ArrayList<String>();
    dbHandler = new MyDBHandler(this,null,null,1);


//This method makes the "Add new workout Button" clickable or not depending on user input
public void inputTextHandler()

    userWorkoutInput.addTextChangedListener(
            new TextWatcher() 
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) 

                

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) 
                    boolean isEmpty = false;
                    if ((userWorkoutInput.getText().toString().trim()).equals("")) 
                        isEmpty = true;
                    
                    addNewWorkoutButton.setEnabled(!isEmpty);
                

                @Override
                public void afterTextChanged(Editable s) 

                
            
    );


/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
THIS IS THE BUTTON LISTENER FOR @id+/addNewWorkoutButton
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
public void addWorkoutButtonClicked(View view)
    String input = (userWorkoutInput.getText().toString().trim());
    if (!input.equals(""))
        addItemToList(input);
        userWorkoutInput.setText("");   //Empties the edit text section
        saveDataToDatabase(input);
    


public void saveDataToDatabase(String input)
    //GIVE THE EXERCISES OBJ VALUES!
    Exercises exercises = new Exercises(input, workoutClicked);
    dbHandler.addExerciseToDatabase(exercises);


public void loadDataFromDatabase()

    String exerName = dbHandler.getExercisesForBodyParts(workoutClicked);

    //IF STATEMENT WEEDS OUT EMPTY DATA
    if(!(exerName.trim().equals(""))) 
        String delim = ",";
        String[] tokens = exerName.split(delim);
        for (int i = 0; i < tokens.length; i++) 
            addItemToList(tokens[i]);
        
    


public void addItemToList(String input)

    itemHold.add(input);
    edsAdapter = new CustomExerciseAdapter(this, itemHold);

    exerciseListView.setAdapter(edsAdapter);
    edsAdapter.notifyDataSetChanged();

    exerciseListView.setOnItemClickListener(
            new AdapterView.OnItemClickListener() 
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
                    exerciseClickedbyUser = String.valueOf(parent.getItemAtPosition(position));
                    textClicked(view, exerciseClickedbyUser);  //starts intent and sends to Exercise Clicked Activity
                
            
    );



/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 This method is an onClick Method from exercise_custom_row.xml
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

public void deleteButtonClicked(View view)
    dbHandler.deleteExerciseFromDatabase(exerciseClickedbyUser, workoutClicked);
    itemHold.remove(exerciseClickedbyUser);

    edsAdapter.notifyDataSetChanged();

    Toast.makeText(getBaseContext(),"Exercise Deleted", Toast.LENGTH_SHORT).show();


/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 This method gets the data (name of section clicked) from MainActivity
 and changes the textView in exercise_section accordingly
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
public void handleIntentData()

    Bundle workoutData = getIntent().getExtras();
    if (workoutData == null)
        return;
    

    workoutClicked = workoutData.getString("exerciseChosen");
    TextView exerciseChosenText = (TextView) findViewById(R.id.exerciseChosenText);
    exerciseChosenText.setText(workoutClicked);
    exerciseChosenText.setTypeface(null, Typeface.BOLD);




public void textClicked(View view, String exercise)

    Intent i = new Intent(this, ExerciseClicked.class);
    i.putExtra("exerciseClicked", exercise);
    startActivity(i);


【问题讨论】:

为什么要在onClick中设置Adapter(用setAdapter方法)? 发布您的适配器。它是直接从数据库中获取数据吗? 在重新加载适配器后调用notifyDataSetChanged()没有意义...你在重新加载它吗? 【参考方案1】:

在我的应用程序中,我根本不使用 notifyDataSetChanged。要刷新 ListView,我只需再次运行数据库查询并使用CursorAdapter.changeCursor。它会根据需要自动调用notifyDataSetChanged

【讨论】:

对不起,这可能是一个愚蠢的问题,但是您在哪里使用 CursorAdapter.chageCursor ? In the method I wrote to refresh the ListView, after the database query.【参考方案2】:

您的项目正在从数据库中删除,但列表视图没有在视觉上更新。设置适配器是一种解决方案,但它会从头开始重置列表,这不会为用户再次滚动提供良好的体验。你可以做一个当您同时从数据库中删除项目时,您可以从列表中删除选定的项目。我认为您的列表视图侦听器在您的活动中应该如下所示:

listview.setOnItemClickListener(new OnItemClickListener() 
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) 
                deleteButtonClicked(postion);
            
        );



public void deleteButtonClicked(int position)
           int count=dbHandler.deleteExerciseFromDatabase(exerciseClickedbyUser, workoutClicked);
    if(count>0)
        list.remove(position);

            edsAdapter.notifyDataSetChanged();
            Toast.makeText(getBaseContext(),"Exercise Deleted", Toast.LENGTH_SHORT).show();
    

【讨论】:

感谢您的建议,抱歉,这可能是一个愚蠢的问题,但我对此很陌生(3 天前开始)。我似乎对 list.remove(position) 有困难。你从哪里得到这个位置变量? 我做到了,顺便说一句,我没有使用我在要从列表中删除的字符串中传递的位置,但是它似乎仍然无法正常工作。这是我更改的dbHandler.deleteExerciseFromDatabase(exerciseClickedbyUser, workoutClicked); itemHold.remove(exerciseClickedbyUser); edsAdapter.notifyDataSetChanged(); 你检查过我编辑的答案吗?请这样做。 我确实尝试了编辑后的答案,但它似乎在 setOnItemClickListener 上给了我“无法解决符号”错误 兄弟,您必须使用您的列表视图实例,然后必须在此设置监听器。【参考方案3】:

您可以使用以下代码完美地从适配器中删除项目。

mCollection.remove(position);
mListLayout.removeAllViews();
notifyDataSetChanged();

【讨论】:

【参考方案4】:

您的列表视图似乎没有变化,因为您分配给适配器的 ArrayList 或 Array 没有任何变化。请也从 ArrayList 或数组中删除该项目。而你只需要调用 notifyDataSetChanged() 。即不需要再次调用 listview.setAdapter(adapter) 。

编辑:

请用下面显示的代码替换您的 customArrayAdapter

   private  ArrayList<String> workouts;

    public CustomExerciseAdapter(Context context, ArrayList<String> workouts) 
        super(context, R.layout.exercise_custom_row, workouts);
        this.workouts = workouts;
    

    @Override
    public View getView(int position, View convertView, ViewGroup parent) 
        LayoutInflater inflater = LayoutInflater.from(getContext());
        View customView = inflater.inflate(R.layout.exercise_custom_row, parent, false);
                /////here change to 
        String singleExerciseItem = (String)workouts.get(position);
        TextView exerciseTV = (TextView) customView.findViewById(R.id.exerciseTV);
        exerciseTV.setText(singleExerciseItem);

        return customView;
    


    public void setList(ArrayList<String> workouts)

       this.workouts = workouts;
       notifyDatasetChanged();

    

在您的删除方法中,在更新数据库和列表后,调用 adapter.setList(workouts),。它可能会为您解决问题。

【讨论】:

嗨@Ansal Ali,我添加了以下 itemHold.remove(exerciseClickedbyUser); edsAdapter.notifyDataSetChanged();但我似乎得到了相同的结果。还有什么我错过了 删除 edsAdapter.notifyDataSetChanged(); from 不会对您的列表视图产生任何影响。请检查并确认。 如果没有任何效果意味着视图保持不变并且“未刷新”那么是的,没有效果 您从父活动中删除一行而不是从适配器中删除...对吗?? 添加item后,需要调用notifyDatasetChanged()吗?【参考方案5】:

感谢所有帮助的人,但最后我想出的答案与你的完全不同。我最终使用了他的方法 [1]:http://jmsliu.com/2444/click-button-in-listview-and-get-item-position.html/“here”,这对我来说绝对完美。无论如何,这对于那些可能遇到同样问题的人来说是这样做的。

在 .JAVA 文件中的 GetView() 方法中粘贴此代码会使 XML 文件膨胀。

Button deleteButton = (Button) customView.findViewById(R.id.deleteButton);
deleteButton.setTag(position);

然后将其添加到您的按钮单击侦听器/onClick 方法中

    int position = (Integer) view.getTag();
    list.remove(position);

    adapter.notifyDataSetChanged();

【讨论】:

【参考方案6】:

删除项目后总是添加以下两行

            notifyDataSetChanged();
            notifyDataSetInvalidated();

notifydatasetchanged 将查看列表中的任何更改 并且 notifydatasetinvalidated 将检查是否有任何项目被删除然后它会更新列表

【讨论】:

以上是关于从中删除项目后 ListView 不“刷新”的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 中刷新 ListView

删除数据库行后刷新自定义游标适配器

Flutter ListView删除项目不起作用

OnTap 后刷新 Flutter ListView

ListView 仅在刷新后显示项目

android从broadcastreceiver刷新listview