我创建了一个ArrayList
with custom ArrayAdater
。每个都ListItem
包含 aCheckBox
和 a TextView
。
TextView 包含目录的名称,而 CheckBox 指示是否应扫描该目录。
我正在维护一个ArrayList
存储所有已检查目录名称的目录。ListView 中有一些buttons
向下。
最初,当我选中/取消选中应用程序时,ArrayList 工作正常并在其中添加/删除元素。
但是当我按下任何按钮时,ArrayList 会冻结并且不会添加/删除元素。
下面的代码:(对不起,长度)
MainActivity 类:
public class MainActivity extends ListActivity implements OnClickListener {
Button done, cancel, selectAll, back;
ListView listView;
ArrayAdapter<Directory> adapter;
List<Directory> list;
ArrayList<String> checkedList;
private final static String ROOT = "/";
private String currentDir; // Used at the time of back button press
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
setContentView(R.layout.main);
checkedList = new ArrayList<String>();
done = (Button) findViewById(R.id.bDone);
back = (Button) findViewById(R.id.bBack);
cancel = (Button) findViewById(R.id.bCancel);
selectAll = (Button) findViewById(R.id.bSelAll);
done.setOnClickListener(this);
back.setOnClickListener(this);
cancel.setOnClickListener(this);
currentDir = ROOT;
new AsyncHandler(this, ROOT).execute();
} catch (Exception e) {
Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// super.onListItemClick(l, v, position, id);
try {
Directory d = list.get(position);
File f = d.getFile();
if (f.isDirectory() && f.canRead()) {
// Updating View on List TextView item click
currentDir = f.getAbsolutePath();
new AsyncHandler(this, f.getAbsolutePath()).execute();
} else {
Toast.makeText(this, f.getName() + " NOT READABLE",
Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show();
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.bDone:
ArrayList<String> localCheckedList = checkedList;
checkedList = filterCheckedList();
String allCkecdDirs = "";
for (int i = 0; i < checkedList.size(); i++) {
allCkecdDirs = allCkecdDirs + "\n" + checkedList.get(i);
}
Toast.makeText(this, allCkecdDirs, Toast.LENGTH_LONG).show();
break;
case R.id.bBack:
if(!currentDir.equals(ROOT)){
/*
* here backtracking current directory one step
* if current die = /mnt/sdcard/music
* so now it will be /mnt/sdcard
* this is because if Back button is pressed,
* in ElementAdapter while rendering elements
* the currentDir will become /mnt/sdcard/music/music
*/
currentDir = new File(currentDir).getParent();
new AsyncHandler(this, currentDir).execute();
}else{
Toast.makeText(this, "Listing already at Root Folder", Toast.LENGTH_LONG).show();
}
break;
case R.id.bCancel:
this.finish();
break;
}
}
private ArrayList<String> filterCheckedList() {
/*
* Removing duplicates
*/
HashSet hs = new HashSet();
hs.addAll(checkedList);
checkedList.clear();
checkedList.addAll(hs);
/*
* Deleting sub-folders if their parent folder has already been added in
* the list
*/
Collections.sort(checkedList);
ArrayList<String> filteredList = new ArrayList<String>();
for (int i = 0; i < checkedList.size(); i++) {
File current = new File(checkedList.get(i));
File parent = current;
while ((parent = parent.getParentFile()) != null) {
if (checkedList.contains(parent.getAbsolutePath())) {
current = parent;
}
}
if (current != null
&& !filteredList.contains(current.getAbsolutePath())) {
filteredList.add(current.getAbsolutePath());
}
}
checkedList = filteredList;
return checkedList;
}
public class AsyncHandler extends AsyncTask {
Context context;
String currentFolder;
private List<Directory> prevList;
public AsyncHandler(Context c, String currentFolder) {
this.context = c;
this.currentFolder = currentFolder;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Object doInBackground(Object... arg0) {
getList();
return null;
}
@Override
protected void onPostExecute(Object result) {
/*
* Checking if list does not contain any directory. If it does not
* then the previous view's list is treated as current list and
* rendered again.
*/
if (list.size() == 0) {
Toast.makeText(context, "No Sub Directory", Toast.LENGTH_SHORT)
.show();
list = prevList;
}
setListAdapter(new ElementAdapter(context, list, checkedList, currentDir));
}
private void getList() {
prevList = list;
list = new ArrayList<Directory>();
File root = new File(currentFolder);
File[] files = root.listFiles();
for (File f : files) {
if (f.isDirectory() && !f.isHidden() && f.canRead()) {
list.add(new Directory(f, f.getName()));
}
}
}
}
}
数组适配器类:
public class ElementAdapter extends ArrayAdapter {
private Context context;
private List<Directory> list;
ArrayList<String> checkedList;
public final String fileName = "AudioSessionFile";
SharedPreferences sharedAudioPrefrences;
private static String currentDir; // This will be appended at the time when
// chcing if the checkbox is aready
// checked or not
public ElementAdapter(Context c, List<Directory> list,
ArrayList checkedList, String currentDir) {
super(c, R.layout.row, list);
this.context = c;
sharedAudioPrefrences = c.getSharedPreferences(fileName,
Context.MODE_PRIVATE);
this.list = list;
this.checkedList = checkedList;
this.currentDir = currentDir;
}
static class ViewHolder {
protected TextView textView;
protected CheckBox checkBox;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
View view = convertView;
if (view == null) {
LayoutInflater inflator = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflator.inflate(R.layout.row, null);
viewHolder = new ViewHolder();
viewHolder.textView = (TextView) view.findViewById(R.id.tvElement);
viewHolder.checkBox = (CheckBox) view.findViewById(R.id.checkBox1);
viewHolder.checkBox
.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
int getPosition = (Integer) buttonView.getTag();
list.get(getPosition).setSelected(
buttonView.isChecked());
/*
* Code to check if checkbox is checked on
* unchecked. If checked then, the corresponding
* entry is made in the HashMap (which contains the
* state of directories to be scanned)
*/
if (isChecked
&& !checkedList.contains(list
.get(getPosition).getFile()
.getAbsolutePath())) {
/*
* Here we can also put condition &&
* !checkedList
* .contains(list.get(getPosition).getFile
* ().getParent()) to avoid creating unnecessary
* entries
*/
checkedList.add(list.get(getPosition).getFile()
.getAbsolutePath());
} else if (!isChecked
&& checkedList.contains(list
.get(getPosition).getFile()
.getAbsolutePath())) {
checkedList.remove(list.get(getPosition)
.getFile().getAbsolutePath());
}
}
});
view.setTag(viewHolder);
view.setTag(R.id.tvElement, viewHolder.textView);
view.setTag(R.id.checkBox1, viewHolder.checkBox);
} else {
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.checkBox.setTag(position);
viewHolder.textView.setText(list.get(position).getName());
viewHolder.checkBox.setChecked(list.get(position).isSelected());
/*
* checking if the directory is already selected earlier by the user
*/
String absPath = currentDir + "/" + viewHolder.textView.getText();
if (checkedList != null
&& checkedList.contains(absPath)) {
viewHolder.checkBox.setChecked(true);
}
return view;
}
}
虽然代码确实进入了 ElementAdapter 中的 onCheckedChangeListener,但是当流返回到 Activity 类时,列表保持原样。