为什么原始数组项也会在 ArrayAdapter 中被删除?
Why the original array items are also get deleted in an ArrayAdapter?
我通过适配器的 add() 和 clear() 从适配器对象中添加和删除值,它们正在从列表中删除和添加元素,该列表未从适配器内的任何位置引用。我有一个 orig 列表,它位于适配器外部,并且有一个从适配器内部到未更改的外部参考的引用,在适配器内部我只引用了一个 new 列表,我填写了使用具有相同对象的旧原始列表。怎么新榜单影响老榜单了?
class LanguageItemArrayAdapter extends ArrayAdapter<com.anysoftkeyboard.ui.settings.LanguageItem>{
private Context mContext;
private final ArrayList<com.anysoftkeyboard.ui.settings.LanguageItem> origList = new ArrayList<com.anysoftkeyboard.ui.settings.LanguageItem>();
private final ArrayList<com.anysoftkeyboard.ui.settings.LanguageItem> filteredList = new ArrayList<com.anysoftkeyboard.ui.settings.LanguageItem>();
LanguageItemArrayAdapter(@NonNull Context context, @LayoutRes ArrayList<com.anysoftkeyboard.ui.settings.LanguageItem> list, ArrayList<com.anysoftkeyboard.ui.settings.LanguageItem> filteredList){
super(context, 0, filteredList);
mContext = context;
origList.addAll(list); //THIS WORKS WELL.
//THIS BREAKS EVERYTHING ->
//origlist = list;
}
public void fillData(){
filteredList.addAll(origList);
notifyDataSetChanged();
}
@Override
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
View listItem = convertView;
if (listItem == null)
listItem = LayoutInflater.from(mContext).inflate(R.layout.languages_list_row, parent, false);
com.anysoftkeyboard.ui.settings.LanguageItem currentItem = filteredList.get(position);
TextView title = listItem.findViewById(R.id.title);
title.setText(currentItem.getTitle());
return listItem;
}
private Filter myFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
ArrayList<com.anysoftkeyboard.ui.settings.LanguageItem> tempList=new ArrayList<com.anysoftkeyboard.ui.settings.LanguageItem>();
//constraint is the result from text you want to filter against.
//objects is your data set you will filter from
if(constraint != null) {
int length= origList.size();
int i=0;
while(i<length){
LanguageItem item= origList.get(i);
if(item.toString().toUpperCase().contains(constraint.toString().toUpperCase())) {
tempList.add(item);
}
i++;
}
//following two lines is very important
//as publish result can only take FilterResults objects
filterResults.values = tempList;
filterResults.count = tempList.size();
}
return filterResults;
}
//HERE ARE THE AFFECTING METHODS:
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filteredList.clear();
clear(); //******THIS METHOD REMOVES THE VALUES from origList as well******
filteredList.addAll((Collection<? extends LanguageItem>) results.values);
notifyDataSetChanged();
//*****THIS ADDS VALUES TO ORIG LIST AS WELL. WHY?*****
for(LanguageItem item: filteredList)
add(item);
}
};
@Override
public Filter getFilter() {
return myFilter;
}
}
为什么原始列表得到编辑,而我只更改过滤后的列表?
编辑:
ArrayAdapter<com.anysoftkeyboard.ui.settings.LanguageItem> adapter = new LanguageItemArrayAdapter(getContext(), simpleLanguageItems, simpleLanguageItems);
((LanguageItemArrayAdapter) adapter).fillData();;
(我知道修复方法,但我不明白原因 - 如果您像我一样遇到自定义适配器过滤器的问题,修复方法在下面的代码中。)
此代码将 ArrayList
的相同实例传递给 LanguageItemArrayAdapter
new LanguageItemArrayAdapter(getContext(), simpleLanguageItems, simpleLanguageItems)
要理解为什么 ArrayAdapter
中的 add(…)
和 clear()
也修改同一个对象,您需要从 source.
查看它们的实现
public void clear() {
synchronized (mLock) {
if (mOriginalValues != null) {
mOriginalValues.clear();
} else {
mObjects.clear();
}
…
}
…
}
clear()
将修改 mObjects
和 mOriginalValues
(您会注意到 ArrayAdapter
中的其他函数做同样的事情)。您将需要阅读 ArrayFilter
中的代码以了解它们是如何修改的。
private class ArrayFilter extends Filter {
/*
mObjects will contain only items fulfilling the filter conditions.
Original items are copied into mOriginalValues
*/
}
查看构造函数(和构造函数链)你会发现你的 class 构造函数有
super(context, 0, filteredList);
最终会调用
private ArrayAdapter(@NonNull Context context,
@LayoutRes int resource,
@IdRes int textViewResourceId,
@NonNull List<T> objects,
boolean objsFromResources) {
…
mObjects = objects;
…
}
这允许 ArrayAdapter
修改您的 simpleLanguageItems
实例。
我通过适配器的 add() 和 clear() 从适配器对象中添加和删除值,它们正在从列表中删除和添加元素,该列表未从适配器内的任何位置引用。我有一个 orig 列表,它位于适配器外部,并且有一个从适配器内部到未更改的外部参考的引用,在适配器内部我只引用了一个 new 列表,我填写了使用具有相同对象的旧原始列表。怎么新榜单影响老榜单了?
class LanguageItemArrayAdapter extends ArrayAdapter<com.anysoftkeyboard.ui.settings.LanguageItem>{
private Context mContext;
private final ArrayList<com.anysoftkeyboard.ui.settings.LanguageItem> origList = new ArrayList<com.anysoftkeyboard.ui.settings.LanguageItem>();
private final ArrayList<com.anysoftkeyboard.ui.settings.LanguageItem> filteredList = new ArrayList<com.anysoftkeyboard.ui.settings.LanguageItem>();
LanguageItemArrayAdapter(@NonNull Context context, @LayoutRes ArrayList<com.anysoftkeyboard.ui.settings.LanguageItem> list, ArrayList<com.anysoftkeyboard.ui.settings.LanguageItem> filteredList){
super(context, 0, filteredList);
mContext = context;
origList.addAll(list); //THIS WORKS WELL.
//THIS BREAKS EVERYTHING ->
//origlist = list;
}
public void fillData(){
filteredList.addAll(origList);
notifyDataSetChanged();
}
@Override
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
View listItem = convertView;
if (listItem == null)
listItem = LayoutInflater.from(mContext).inflate(R.layout.languages_list_row, parent, false);
com.anysoftkeyboard.ui.settings.LanguageItem currentItem = filteredList.get(position);
TextView title = listItem.findViewById(R.id.title);
title.setText(currentItem.getTitle());
return listItem;
}
private Filter myFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
ArrayList<com.anysoftkeyboard.ui.settings.LanguageItem> tempList=new ArrayList<com.anysoftkeyboard.ui.settings.LanguageItem>();
//constraint is the result from text you want to filter against.
//objects is your data set you will filter from
if(constraint != null) {
int length= origList.size();
int i=0;
while(i<length){
LanguageItem item= origList.get(i);
if(item.toString().toUpperCase().contains(constraint.toString().toUpperCase())) {
tempList.add(item);
}
i++;
}
//following two lines is very important
//as publish result can only take FilterResults objects
filterResults.values = tempList;
filterResults.count = tempList.size();
}
return filterResults;
}
//HERE ARE THE AFFECTING METHODS:
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filteredList.clear();
clear(); //******THIS METHOD REMOVES THE VALUES from origList as well******
filteredList.addAll((Collection<? extends LanguageItem>) results.values);
notifyDataSetChanged();
//*****THIS ADDS VALUES TO ORIG LIST AS WELL. WHY?*****
for(LanguageItem item: filteredList)
add(item);
}
};
@Override
public Filter getFilter() {
return myFilter;
}
}
为什么原始列表得到编辑,而我只更改过滤后的列表?
编辑:
ArrayAdapter<com.anysoftkeyboard.ui.settings.LanguageItem> adapter = new LanguageItemArrayAdapter(getContext(), simpleLanguageItems, simpleLanguageItems);
((LanguageItemArrayAdapter) adapter).fillData();;
(我知道修复方法,但我不明白原因 - 如果您像我一样遇到自定义适配器过滤器的问题,修复方法在下面的代码中。)
此代码将 ArrayList
的相同实例传递给 LanguageItemArrayAdapter
new LanguageItemArrayAdapter(getContext(), simpleLanguageItems, simpleLanguageItems)
要理解为什么 ArrayAdapter
中的 add(…)
和 clear()
也修改同一个对象,您需要从 source.
public void clear() {
synchronized (mLock) {
if (mOriginalValues != null) {
mOriginalValues.clear();
} else {
mObjects.clear();
}
…
}
…
}
clear()
将修改 mObjects
和 mOriginalValues
(您会注意到 ArrayAdapter
中的其他函数做同样的事情)。您将需要阅读 ArrayFilter
中的代码以了解它们是如何修改的。
private class ArrayFilter extends Filter {
/*
mObjects will contain only items fulfilling the filter conditions.
Original items are copied into mOriginalValues
*/
}
查看构造函数(和构造函数链)你会发现你的 class 构造函数有
super(context, 0, filteredList);
最终会调用
private ArrayAdapter(@NonNull Context context,
@LayoutRes int resource,
@IdRes int textViewResourceId,
@NonNull List<T> objects,
boolean objsFromResources) {
…
mObjects = objects;
…
}
这允许 ArrayAdapter
修改您的 simpleLanguageItems
实例。