调用notifyDataSetChanged()后,Android ListView没有udpating

时间:2015-01-21 22:41:11

标签: android listview android-arrayadapter

我不确定原因,但是在调用notifyOnDataSetChanged()之后ListView没有更新/重绘。我也尝试在列表视图上调用invalidateViews(),但这也没有奏效。有什么建议?我应该覆盖notifyOnDataSetChanged()?

以下是ListActivity

    package com.example.czhou.myapplication2;

import android.app.Activity;
import android.content.ContentProviderOperation;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

import android.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

import java.io.File;
import java.io.FileOutputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;

/**
 * Created by czhou on 1/18/2015.
 */
public class SudokuListActivity extends ActionBarActivity{

    public static String[] fileNames;
    public SudokuListAdapter mAdapter;
    public static File[] files;
    public static ArrayList<Integer> selected = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
         Context c = this;

        setContentView(R.layout.activity_list);

         ListView lv = (ListView) findViewById(R.id.listView);
        lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
        lv.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {

            @Override
            public void onItemCheckedStateChanged(ActionMode mode, int position,
                                                  long id, boolean checked) {
                if (checked) {
                    if (selected.indexOf(position) == -1) {
                        selected.add(position);
                    }
                }
                // Here you can do something when items are selected/de-selected,
                // such as update the title in the CAB
            }

            @Override
            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                // Respond to clicks on the actions in the CAB
                switch (item.getItemId()) {
                    case R.id.delete:
                            List<String> toRemove = new ArrayList<String>();
                        List<String> lst = new ArrayList<String>(Arrays.asList(fileNames));
                        for (int i = 0; i < selected.size(); i++) {
                            toRemove.add(fileNames[selected.get(i)]);
                        }


                            lst.removeAll(toRemove);
                        for (int j = 0; j < toRemove.size();j++) {
                            File file = getFileStreamPath("puzzle" + toRemove.get(j));
                            file.delete();
                        }
                            fileNames = lst.toArray(fileNames);
                            mAdapter.notifyDataSetChanged();



                        mode.finish(); // Action picked, so close the CAB
                        return true;
                    default:
                        return false;
                }
            }

            @Override
            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                // Inflate the menu for the CAB
                MenuInflater inflater = mode.getMenuInflater();
                inflater.inflate(R.menu.activity_list_cab, menu);
                return true;
            }

            @Override
            public void onDestroyActionMode(ActionMode mode) {
                // Here you can make any necessary updates to the activity when
                // the CAB is removed. By default, selected items are deselected/unchecked.
            }

            @Override
            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                // Here you can perform updates to the CAB due to
                // an invalidate() request
                return false;
            }
        });




        files = c.getFilesDir().listFiles();
        fileNames = new String[files.length];
        for (int i = 0; i < files.length; i++) {
            fileNames[i] = files[i].getName().substring(6,files[i].getName().length());
        }


        mAdapter = new SudokuListAdapter(this,R.layout.row,fileNames);
        lv.setAdapter(mAdapter);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater menuInflater = getMenuInflater();
        menuInflater.inflate(R.menu.activity_list_menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        Context c = this;
        switch (item.getItemId()) {
            case R.id.add:
                DateFormat dateFormat = new SimpleDateFormat("dd MMMM yy hh:mm:ss a");
                Calendar cal = Calendar.getInstance();

                String fn = "puzzle" + dateFormat.format(cal.getTime());
                SudokuGen sg = new SudokuGen();
                CellField cf = sg.generate();

                FileOutputStream outputStream;

                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < 9; i++) {
                    for (int j = 0; j < 9; j++) {
                        if (cf.field[i][j].isEditable) {
                            sb.append(",");
                        } else {
                            sb.append(".");
                        }
                        if (cf.field[i][j].isWrong) {
                            sb.append("!");
                        } else {
                            sb.append(".");
                        }

                        sb.append(cf.field[i][j].getValue());
                    }
                }

                try {

                    outputStream = openFileOutput(fn, Context.MODE_PRIVATE);
                    outputStream.write(sb.toString().getBytes());
                    outputStream.close();
                    System.out.println("Saving... ");
                } catch (Exception e) {
                    e.printStackTrace();
                }

                Intent intent = new Intent(this, SudokuGameActivity.class);
                intent.putExtra("FILE",fn);
                startActivity(intent);
            break;
            default:

        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onRestart() {
        System.out.println("restarting.. ");
        Context c = this;

        setContentView(R.layout.activity_list);

        final ListView lv = (ListView) findViewById(R.id.listView);




        files = c.getFilesDir().listFiles();
        fileNames = new String[files.length];
        for (int i = 0; i < files.length; i++) {
            fileNames[i] = files[i].getName().substring(6,files[i].getName().length());
        }


        mAdapter = new SudokuListAdapter(this,R.layout.row ,fileNames);
        lv.setAdapter(mAdapter);

        lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
        lv.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {

            @Override
            public void onItemCheckedStateChanged(ActionMode mode, int position,
                                                  long id, boolean checked) {
                if (checked) {
                    if (selected.indexOf(position) == -1) {
                        selected.add(position);
                    }
                }
                // Here you can do something when items are selected/de-selected,
                // such as update the title in the CAB
            }

            @Override
            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                // Respond to clicks on the actions in the CAB
                switch (item.getItemId()) {
                    case R.id.delete:
                        List<String> toRemove = new ArrayList<String>();
                        List<String> lst = new ArrayList<String>(Arrays.asList(fileNames));
                        for (int i = 0; i < selected.size(); i++) {
                            toRemove.add(fileNames[selected.get(i)]);
                        }


                        lst.removeAll(toRemove);
                        for (int j = 0; j < toRemove.size();j++) {
                            File file = getFileStreamPath("puzzle" + toRemove.get(j));
                            file.delete();
                        }
                        fileNames = lst.toArray(fileNames);
                        mAdapter.notifyDataSetChanged();



                        mode.finish(); // Action picked, so close the CAB
                        return true;
                    default:
                        return false;
                }
            }

            @Override
            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                // Inflate the menu for the CAB
                MenuInflater inflater = mode.getMenuInflater();
                inflater.inflate(R.menu.activity_list_cab, menu);
                return true;
            }

            @Override
            public void onDestroyActionMode(ActionMode mode) {
                // Here you can make any necessary updates to the activity when
                // the CAB is removed. By default, selected items are deselected/unchecked.
            }

            @Override
            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                // Here you can perform updates to the CAB due to
                // an invalidate() request
                return false;
            }
        });

        super.onRestart();
    }


}

以下是ListAdapter

package com.example.czhou.myapplication2;

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.io.File;
import java.util.zip.Inflater;

/**
 * Created by czhou on 1/18/2015.
 */
public class SudokuListAdapter extends ArrayAdapter<String> {
    Context context;
    String data[];
    private static LayoutInflater inflater = null;

    public  SudokuListAdapter(Context context,int id,String data[]){
        super(context,id,data);
        // TODO Auto-generated constructor stub
        this.context = context;
        this.data = data;
        inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
    @Override
    public int getCount() {
        return data.length;
    }

    @Override
    public String getItem(int position) {
        return data[position];
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View vi = convertView;
        if (vi == null)
            vi = inflater.inflate(R.layout.row, null);
        TextView text = (TextView) vi.findViewById(R.id.date);
        text.setText(data[position]);
        System.out.println("pos: " + position);

//        Bundle b = new Bundle();
//        b.putString("FILE","puzzle" + data[position]);
        SudokuPreviewView view = (SudokuPreviewView) vi.findViewById(R.id.preview);
        view.setData("puzzle" + data[position]);
        return vi;
    }


    public void setData(String[] data) {
        this.data = data;
    }

    public void updateData(String newData[]) {
        this.data = newData;

    }
}

这是row.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="5dp">

    <com.example.czhou.myapplication2.SudokuPreviewView
        android:layout_width="203dp"
        android:layout_height="258dp"
        android:id="@+id/preview"
        custom:mCell="15dp"
        custom:mTextSize="7sp"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Last played: 1/1/1"
        android:id="@+id/date"
        android:layout_gravity="right"
        android:layout_alignBottom="@+id/preview"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true" />
</RelativeLayout>

2 个答案:

答案 0 :(得分:0)

您的适配器内部似乎正在修改集合fileNames而不是data,这就是为什么您没有看到ListView的任何更新。

答案 1 :(得分:0)

我认为这是你的问题:

fileNames = lst.toArray(fileNames);
mAdapter.notifyDataSetChanged();

您指定了fileNames但从未在适配器中设置此数据。适配器已通知但仍有旧数据。

引用fileNames指向与Adapter的数据不同的内容。

这应该有效:

fileNames = lst.toArray(fileNames);
mAdapter.setData(fileNames);
mAdapter.notifyDataSetChanged();

我注意到的另一件事是你在UI线程上做I / O,考虑使用一个单独的线程。我只是快速查看代码,没有检查它是否真的有用。

编辑:

ArrayAdapter有自己的添加/删除项目的方法,因此您实际上不需要使用自定义方法执行此操作。也许这适合你:

fileNames = lst.toArray(fileNames);
mAdapter.clear();
mAdapter.addAll(fileNames); // this will update your list automatically

或者,您可以直接使用您的列表:

mAdapter.clear();
mAdapter.addAll(lst);