android - ViewHolder 模式 - 如何正确更新 View

标签 android listview android-viewholder

在扩展的 ArrayAdapter 中实现 viewHolder 模式,并在 Linear Layout 上实现 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;
     }
}

最佳答案

你在做什么

当前可见的行位于位置 0,1,2。您正在更新一个特定的ViewHolder,该ViewHolder已被设置为特定(为了使用更好的词) View 的标签。稍后当您调用 holder = (ViewHolder)rowview.getTag() 时,会重新使用该 View 。为了便于解释,我们假设您正在更新位置 1 处的 View 。

滚动 listView 时会发生什么

当您滚动 ListView 时,通过从标签获取持有者来重新使用旧 View 。这意味着您之前更改的 View 现在被重新使用。

您需要做什么

因此,当您需要更新 View 时,首先更新相关变量。例如:

在 CustomCommunityQuestion 类中创建一个属性并实现如下所示的 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);
}

希望对你有帮助!

关于android - ViewHolder 模式 - 如何正确更新 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35623303/

相关文章:

android - 如何使用 firebase 查询过滤 android listview 项目?

flutter - 在 flutter 中将 Firebase 数据获取为 Listview 构建器

android - 带有 Scrapped 或附加 View 的 GapWorker 可能不会被回收。 isScrap :false isAttached:true

android - RecyclerView ViewHolder 中的 ConstraintLayout 性能

android - 在viewpager中保存和恢复 fragment 状态

android - Android Studio导出jar不导出任何jar

android - 不同机器之间的 lint 差异

android - 包含 Robolectric 时 Espresso 测试中的 java.lang.NoClassDefFoundError

c# - 通过按钮在 ListView 中进行单选

android - 在 GridView 持有者模式中显示多次的复选框