ViewHolder 模式 - 如何正确更新视图
ViewHolder pattern - How to correctly update views
在扩展的 ArrayAdapter 中实现 viewHolder 模式,并在线性布局中实现 onClickListener 时,此 LinearLayout 的背景颜色发生了变化但对于其他随机行也是如此!
这是我的代码(已删除 viewHolder 以仅包含错误):
public class CustomFeedsAdapter extends ArrayAdapter<CustomCommunityQuestion>{
private static final String TAG = "CustomFeedsAdapter";
private Context context;
private ArrayList<CustomCommunityQuestion> customCommunityQuestions;
public CustomFeedsAdapter(Context context, ArrayList<CustomCommunityQuestion> customCommunityQuestions) {
super(context, -1, customCommunityQuestions);
this.context = context;
this.customCommunityQuestions = customCommunityQuestions;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
// reuse views
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflater.inflate(R.layout.cards_feeds_row, null, false);
holder.buttonFollow = (LinearLayout) rowView.findViewById(R.id.follow_layout);
rowView.setTag(holder);
} else {
holder = (ViewHolder) rowView.getTag();
}
final CustomCommunityQuestion currentQuestion = customCommunityQuestions.get(position);
// Set onClick Listeners
holder.buttonFollow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
VolleySingleton volleySingleton = VolleySingleton.getInstance(context);
StringRequest followJsonObjectRequest = new StringRequest(Request.Method.GET,
"http://private-e9644-popxoandroid.apiary-mock.com/quest_follow/1/0",
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
Log.d(TAG, response);
JSONObject responseObject = new JSONObject(response);
String message = responseObject.getString("message");
Integer success = responseObject.getInt("success");
Toast.makeText(context,message,Toast.LENGTH_SHORT).show();
if(success!=0){
holder.buttonFollow.setBackgroundColor(R.color.holo_blue_bright); // Here the button I wish to update doesn't get the color, but instead some weird random row's button get's changed.
holder.buttonFollow.setEnabled(false);
}
} catch (Exception e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(context, "There was some error! You were unable to follow", Toast.LENGTH_SHORT).show();
error.printStackTrace();
Log.e(TAG,error.getMessage());
}
});
volleySingleton.addToRequestQueue(followJsonObjectRequest);
}
});
return rowView;
}
private class ViewHolder {
private LinearLayout buttonFollow;
}
}
问题是列表项的回收:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
// reuse views
final ViewHolder holder;
if (convertView == null) {
...
} else {
holder = (ViewHolder) rowView.getTag();
//!!!
// here the view item is recycled but
// holder.buttonFollow is not reset to its initial state
}
解决方案:您的 CustomFeedsAdapter
必须记住每个项目的成功统计数据
你在做什么
假设当前可见的行位于位置 0、1、2。您正在更新一个特定的 ViewHolder,它已被设置为特定的标签(使用更好的词)- 视图。稍后调用 holder = (ViewHolder)rowview.getTag()
时会重新使用此视图。为了便于说明,我们假设您正在更新位置 1 的视图。
滚动 listView 时会发生什么
当您滚动列表视图时,旧视图会通过从标签中获取持有者来重新使用。这意味着您之前更改的视图现在正在重新使用。
你需要做什么来代替
所以当你需要更新你的视图时,首先更新一个相关的变量。例如:
在您的 CustomCommunityQuestion class 中创建一个属性并实现 getter 和 setter,如下所示:
boolean isBlue;
public void setIsBlue(booelan isblue){
this.isBlue = isblue;
}
public boolean isBlue(){
return isBlue;
}
现在在您的按钮 onClickListener 中,您可以将变量 isBlue 设置为 yes,然后调用 notifyDataSetChanged()
。此外,像这样处理属性 isBlue:
只需检查 isBlue 状态并相应地设置颜色
if(customCommunityQuestions.get(position).isBlue()){
holder.buttonFollow.setBackgroundColor(R.color.holo_blue_bright);
}else{
holder.buttonFollow.setBackgroundColor(R.color.black);
}
希望对您有所帮助!
在扩展的 ArrayAdapter 中实现 viewHolder 模式,并在线性布局中实现 onClickListener 时,此 LinearLayout 的背景颜色发生了变化但对于其他随机行也是如此!
这是我的代码(已删除 viewHolder 以仅包含错误):
public class CustomFeedsAdapter extends ArrayAdapter<CustomCommunityQuestion>{
private static final String TAG = "CustomFeedsAdapter";
private Context context;
private ArrayList<CustomCommunityQuestion> customCommunityQuestions;
public CustomFeedsAdapter(Context context, ArrayList<CustomCommunityQuestion> customCommunityQuestions) {
super(context, -1, customCommunityQuestions);
this.context = context;
this.customCommunityQuestions = customCommunityQuestions;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
// reuse views
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflater.inflate(R.layout.cards_feeds_row, null, false);
holder.buttonFollow = (LinearLayout) rowView.findViewById(R.id.follow_layout);
rowView.setTag(holder);
} else {
holder = (ViewHolder) rowView.getTag();
}
final CustomCommunityQuestion currentQuestion = customCommunityQuestions.get(position);
// Set onClick Listeners
holder.buttonFollow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
VolleySingleton volleySingleton = VolleySingleton.getInstance(context);
StringRequest followJsonObjectRequest = new StringRequest(Request.Method.GET,
"http://private-e9644-popxoandroid.apiary-mock.com/quest_follow/1/0",
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
Log.d(TAG, response);
JSONObject responseObject = new JSONObject(response);
String message = responseObject.getString("message");
Integer success = responseObject.getInt("success");
Toast.makeText(context,message,Toast.LENGTH_SHORT).show();
if(success!=0){
holder.buttonFollow.setBackgroundColor(R.color.holo_blue_bright); // Here the button I wish to update doesn't get the color, but instead some weird random row's button get's changed.
holder.buttonFollow.setEnabled(false);
}
} catch (Exception e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(context, "There was some error! You were unable to follow", Toast.LENGTH_SHORT).show();
error.printStackTrace();
Log.e(TAG,error.getMessage());
}
});
volleySingleton.addToRequestQueue(followJsonObjectRequest);
}
});
return rowView;
}
private class ViewHolder {
private LinearLayout buttonFollow;
}
}
问题是列表项的回收:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
// reuse views
final ViewHolder holder;
if (convertView == null) {
...
} else {
holder = (ViewHolder) rowView.getTag();
//!!!
// here the view item is recycled but
// holder.buttonFollow is not reset to its initial state
}
解决方案:您的 CustomFeedsAdapter
必须记住每个项目的成功统计数据
你在做什么
假设当前可见的行位于位置 0、1、2。您正在更新一个特定的 ViewHolder,它已被设置为特定的标签(使用更好的词)- 视图。稍后调用 holder = (ViewHolder)rowview.getTag()
时会重新使用此视图。为了便于说明,我们假设您正在更新位置 1 的视图。
滚动 listView 时会发生什么
当您滚动列表视图时,旧视图会通过从标签中获取持有者来重新使用。这意味着您之前更改的视图现在正在重新使用。
你需要做什么来代替
所以当你需要更新你的视图时,首先更新一个相关的变量。例如:
在您的 CustomCommunityQuestion class 中创建一个属性并实现 getter 和 setter,如下所示:
boolean isBlue;
public void setIsBlue(booelan isblue){
this.isBlue = isblue;
}
public boolean isBlue(){
return isBlue;
}
现在在您的按钮 onClickListener 中,您可以将变量 isBlue 设置为 yes,然后调用 notifyDataSetChanged()
。此外,像这样处理属性 isBlue:
只需检查 isBlue 状态并相应地设置颜色
if(customCommunityQuestions.get(position).isBlue()){
holder.buttonFollow.setBackgroundColor(R.color.holo_blue_bright);
}else{
holder.buttonFollow.setBackgroundColor(R.color.black);
}
希望对您有所帮助!