我不确定原因,但是在调用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>
答案 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);