Android 面临关键问题:使用ViewHolder模式在Listview中切换图像源

Android 面临关键问题:使用ViewHolder模式在Listview中切换图像源,android,listview,xamarin.android,xamarin,android-imageview,Android,Listview,Xamarin.android,Xamarin,Android Imageview,在我的Listview的ListItem中,我有多个控件,其中一个是imageview。我的目的是,当用户单击该图像时,源应该更改为其他内容。我正在实现ViewHolder模式,现在我可以在单击时切换源代码。我当前的问题是,当我向下滚动时,会创建新视图(重复使用),当我尝试再次向上移动时,我切换图像的列表项会再次使用默认图像源创建,因为我的数据源列表保持不变。请帮忙 private class ViewHolder : Java.Lang.Object {

在我的Listview的ListItem中,我有多个控件,其中一个是imageview。我的目的是,当用户单击该图像时,源应该更改为其他内容。我正在实现ViewHolder模式,现在我可以在单击时切换源代码。我当前的问题是,当我向下滚动时,会创建新视图(重复使用),当我尝试再次向上移动时,我切换图像的列表项会再次使用默认图像源创建,因为我的数据源列表保持不变。请帮忙

        private class ViewHolder : Java.Lang.Object
    {
        //Activity context;
        public MyTextView HadithBook;
        public MyTextView HadithChapter;
        public MyTextView HadithText;
        public ImageView FavButton;
        public ImageView ShareButton;
        public EventHandler Handler;
        public MyTextView RowId;
        public MyTextView IsFavorite;
    }


        public override View GetView (int position, View convertView, ViewGroup parent)
    {


        ViewHolder holder = null;
        if (convertView == null) 
        {
            convertView = context.LayoutInflater.Inflate (Resource.Layout.HadithListViewItem, null);
            holder = new ViewHolder ();
            holder.HadithBook = convertView.FindViewById<MyTextView> (Resource.Id.HadithBook);
            holder.HadithChapter = convertView.FindViewById<MyTextView> (Resource.Id.HadithChapter);
            holder.HadithText = convertView.FindViewById<MyTextView> (Resource.Id.HadithText);
            holder.FavButton = convertView.FindViewById<ImageView> (Resource.Id.favButton);
            holder.ShareButton = convertView.FindViewById<ImageView> (Resource.Id.ShareButton);
            holder.IsFavorite = convertView.FindViewById<MyTextView> (Resource.Id.IsFavorite);
            holder.RowId = convertView.FindViewById<MyTextView> (Resource.Id.RowId);

            holder.Handler = (s, e) => FavoriteHandler (s, e, holder);

            convertView.Tag = holder;
        }

        if (holder == null) 
        {
            holder = (ViewHolder)convertView.Tag;

            holder.FavButton.Click -= holder.Handler;
        }

        var item = items[position];

        holder.HadithBook.Text = item.BookName;
        holder.HadithChapter.Text = item.ChapterName + " - " + item.HadithID;

        if (!string.IsNullOrEmpty (keyword) & !string.IsNullOrWhiteSpace (keyword)) {
            holder.HadithText.TextFormatted = (Html.FromHtml (ReplaceEx ((item.HadithText).ToString (), keyword, "<font color='#ff9000'><b>" + keyword + "</b></font>")));
        } else {
            holder.HadithText.TextFormatted =Html.FromHtml(item.HadithText);
        }






        if (holder.FavButton.Tag.Equals(0)) 
        {
            holder.FavButton.Tag = 0;
            holder.FavButton.SetImageResource (Resource.Drawable.ic_action_not_important);

        } else 
        {
            holder.FavButton.Tag = 1;
            holder.FavButton.SetImageResource (Resource.Drawable.ic_action_important);
        }

        holder.FavButton.Click += holder.Handler;
        convertView.SetOnClickListener (null);

        return convertView;
        }


        void FavoriteHandler (object sender, EventArgs e, ViewHolder holder)
    {
        Database db = new Database ();
        if (holder.FavButton.Tag.Equals (0)) {
            holder.FavButton.SetImageResource (Resource.Drawable.ic_action_important);
            holder.FavButton.Tag = 1;
            db.InsertQuery ("insert into favorite values ('" + holder.RowId + "');");

        } else if (holder.FavButton.Tag.Equals (1)) {
            holder.FavButton.SetImageResource (Resource.Drawable.ic_action_not_important);
            holder.FavButton.Tag = 0;
            db.InsertQuery ("Delete from favorite where id ='" + holder.RowId + "';");
        }
        db = null;

    }
私有类视图持有者:Java.Lang.Object
{
//活动语境;
公共MyTextView HadithBook;
公共MyTextView Hadith章;
公共MyTextView HadithText;
公共图像查看按钮;
公共图像查看共享按钮;
公共事件处理程序;
公共MyTextView RowId;
公共MyTextView最受欢迎;
}
公共覆盖视图GetView(int位置、视图转换视图、视图组父视图)
{
ViewHolder=null;
if(convertView==null)
{
convertView=context.LayoutInflater.Inflate(Resource.Layout.HadithListViewItem,null);
holder=新的ViewHolder();
holder.HadithBook=convertView.findviewbyd(Resource.Id.HadithBook);
holder.HadithChapter=convertView.FindViewById(Resource.Id.HadithChapter);
holder.HadithText=convertView.FindViewById(Resource.Id.HadithText);
holder.FavButton=convertView.FindViewById(Resource.Id.FavButton);
holder.ShareButton=convertView.FindViewById(Resource.Id.ShareButton);
holder.IsFavorite=convertView.FindViewById(Resource.Id.IsFavorite);
holder.RowId=convertView.findviewbyd(Resource.Id.RowId);
holder.Handler=(s,e)=>FavoriteMhandler(s,e,holder);
convertView.Tag=holder;
}
if(holder==null)
{
holder=(ViewHolder)convertView.Tag;
holder.FavButton.Click-=holder.Handler;
}
var项目=项目[位置];
holder.HadithBook.Text=item.BookName;
holder.HadithChapter.Text=item.ChapterName+“-”+item.HadithID;
如果(!string.IsNullOrEmpty(关键字)&!string.IsNullOrWhiteSpace(关键字)){
holder.HadithText.TextFormatted=(Html.FromHtml(ReplaceEx((item.HadithText.ToString(),关键字“+”));
}否则{
holder.HadithText.TextFormatted=Html.FromHtml(item.HadithText);
}
if(holder.FavButton.Tag.Equals(0))
{
holder.FavButton.Tag=0;
holder.FavButton.SetImageResource(Resource.Drawable.ic动作不重要);
}否则
{
holder.FavButton.Tag=1;
holder.FavButton.SetImageResource(Resource.Drawable.ic_action_important);
}
holder.FavButton.Click+=holder.Handler;
convertView.SetOnClickListener(空);
返回视图;
}
void FavoriteHandler(对象发送方、事件参数、视图持有者)
{
Database db=新数据库();
if(holder.FavButton.Tag.Equals(0)){
holder.FavButton.SetImageResource(Resource.Drawable.ic_action_important);
holder.FavButton.Tag=1;
db.InsertQuery(“插入到收藏夹值(“+holder.RowId+”);”;
}else if(holder.FavButton.Tag.Equals(1)){
holder.FavButton.SetImageResource(Resource.Drawable.ic动作不重要);
holder.FavButton.Tag=0;
db.InsertQuery(“从收藏夹中删除,其中id=”+holder.RowId+“;”);
}
db=null;
}

在学习如何实现适配器时,几乎每个人都会落入这个陷阱

问题在于,您在viewholder中存储的数据是该位置独有的。例如,在使用值对其进行设置之前,您正在读取holder.FavButton.Tag,因此当前代码希望该标记为您保留数据


当您在listview中滚动时,视图被回收,因此您正在从另一个位置读取数据。不能在视图保持架中缓存位置相关数据。相反,它用于保存所有位置共用的布局元素(即视图是可转换的,因此在getView方法中命名为“convertView”)。您必须通过其他方式缓存该数据,例如通过位置缓存数据的hashmap。

这是monodroid应用程序。我指的是使用C#的Android应用程序。先生,这是非常好的编译,没有编译错误。好的,好的,我将删除我的注释。你的意思是我应该维护一个字典项或哈希表来存储数据,如。。dictionary()然后在单击事件时,我应该相应地更新这个dictionary项,并在getview方法中检查dictionary项中该位置的相应值。这是要走的路吗???酷。。非常感谢…还有一个问题,我应该为所有ListItems维护字典项,还是只为用户单击“切换图像”的列表项维护字典项,因为我的listview大约有3000个ListItems。如果您希望只单击一小部分,则只将收藏夹放在列表中,并使null表示不受青睐。即使你把所有3000名布尔人都交出来,也没什么大不了的。如果这些数据来自本地数据库,android可以非常快速地读取简单的数据库(闪存),并且可以在getView方法中动态填充listview(或者根据需要通过自定义异步方法)。实际上,我在android上有sqlite数据库,我正在用该数据库中的数据填充listview,首先将所有数据读取到列表中,然后使用我的适配器将这些数据加载到listview中。若用户更改了收藏夹,我必须将其写回数据库。最好的方法是什么。