Adapter view on click event returning incorrect po

2019-08-10 21:40发布

The view holder no longer creates duplicates although it returns the incorrect position at times. Console output below as well as current code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
using Android.Text;
using System.Net;
using System.Collections.Specialized;

namespace MyMentor
{
    public class dashboardAdapter : BaseAdapter<DashboardLINQ>
    {
        List<DashboardLINQ> items;
        Activity context;
        int realpos;
        public dashboardAdapter(Activity context, List<DashboardLINQ> items)
            : base()
        {
            this.context = context;
            this.items = items;
        }
        public override long GetItemId(int position)
        {
            return position;
        }
        public override DashboardLINQ this[int position]
        {
            get { return items[position]; }
        }
        public override int Count
        {
            get { return items.Count; }
        }
        public override View GetView(int position, View convertView, ViewGroup parent)
        {
            ServiceViewHolder holder = null;

            Console.WriteLine ("View No If: "+position);
            realpos = position;
            View view = convertView;
            if (view == null) {
                Console.WriteLine ("View == Null: "+position);
                realpos = position;

                holder = new ServiceViewHolder ();
                view = LayoutInflater.From (context).Inflate (Resource.Layout.dashboardItemLayout, null, false);
                holder.like = view.FindViewById<ImageButton> (Resource.Id.button1);
                holder.comment = view.FindViewById<ImageButton> (Resource.Id.button2);
                holder.share = view.FindViewById<ImageButton> (Resource.Id.button3);
                holder.usrname = view.FindViewById<TextView> (Resource.Id.textView1);
                holder.prof = view.FindViewById<ImageView> (Resource.Id.imageView1);

                holder.like.Click += (sender, e) => {
                    WebClient client = new WebClient ();
                    Uri uri = new Uri ("url");
                    NameValueCollection parameters = new NameValueCollection ();
                    parameters.Add ("UID", items [position].MID);
                    parameters.Add ("PID", items [position].ID);
                    client.UploadValuesAsync (uri, parameters);
                }; 

                holder.share.Click += (sender, e) => {
                    int MaxLength = 150;

                    var name = Html.FromHtml (items [position].pDesc).ToString ();
                    if (name.Length > MaxLength) {
                        name = name.Substring (0, MaxLength) + "... My Mentor";
                    }

                    var myIntent = new Intent (Android.Content.Intent.ActionSend);
                    myIntent.PutExtra (Intent.ExtraText, name);
                    myIntent.SetType ("text/plain");
                    this.context.StartActivity (Intent.CreateChooser (myIntent, "Choose an App"));
                };

                holder.usrname.Click += (sender, e) => {
//                  Bundle fragBundle = new Bundle ();
//                  fragBundle.PutString ("image", items [position].uPicLocal);
//                  fragBundle.PutString ("name", items [position].uFullName);
//                  var transaction = this.context.FragmentManager.BeginTransaction ();
//                  var dialogimgview = new DialogImageView ();
//                  dialogimgview.Arguments = fragBundle;
//                  transaction.AddToBackStack (null);
//                  dialogimgview.Show (transaction, "Dialog_Fragment" + position);
                };

                holder.prof.Click += (sender, e) => {
                    Console.WriteLine ("Realpos: "+realpos+"       Position: "+position);
                };
                view.Tag = holder;
            } else {
                holder = view.Tag as ServiceViewHolder;
                Console.WriteLine ("View Not Null: "+position);
            }

            ImageView prof = view.FindViewById<ImageView>(Resource.Id.imageView1);
            Koush.UrlImageViewHelper.SetUrlDrawable (prof, "url"+items [position].uPicLocal);

            TextView usrname = view.FindViewById<TextView> (Resource.Id.textView1);
            usrname.Text = items [position].uFullName;

            TextView date = view.FindViewById<TextView> (Resource.Id.textView2);
            date.Text = items [position].pDate;

            ImageView imagen = view.FindViewById<ImageView>(Resource.Id.imageView2);
            Koush.UrlImageViewHelper.SetUrlDrawable (imagen, "http://www.mymentor.org.za/"+items [position].pImage);

            TextView desc = view.FindViewById<TextView> (Resource.Id.textView3);
            desc.Text = Html.FromHtml (items [position].pDesc).ToString();

            TextView comlike = view.FindViewById<TextView> (Resource.Id.textView4);
            comlike.Text = "Likes: "+items [position].likecnumrows+"    Comments: "+items [position].commentscnumrows;

            return view;
        }

        void Prof_Click (object sender, EventArgs e)
        {
            Toast.MakeText(context, "Position: "+realpos, ToastLength.Long).Show();
        }

        public class ServiceViewHolder : Java.Lang.Object
        {
            public ImageButton like { get; set; }
            public ImageButton comment { get; set; }
            public ImageButton share { get; set; }
            public ImageView prof { get; set; }
            public TextView usrname { get; set; }
        }
    }
}

Below is the console output to show you the tests I have been running

There is alot of console data below so the emphasis should be on -View No If -View == Null -Realpos -Position

Let me know if you need anymore

View No If: 0
View == Null: 0
[art] JNI RegisterNativeMethods: attempt to register 0 native methods for md5c2cbda97c60838cc1822f8363c96ec60.dashboardAdapter_ServiceViewHolder
View No If: 1
View == Null: 1
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] (HTTPLog)-Static: isShipBuild true
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] (HTTPLog)-Static: isShipBuild true
[System.out] (HTTPLog)-Thread-43421-535359947: SmartBonding Enabling is false, SHIP_BUILD is true, log to file is false, DBG is false
[System.out] (HTTPLog)-Thread-43421-535359947: SMARTBONDING_FEATURE_ENABLED is true
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] (HTTPLog)-Thread-43420-520578202: SmartBonding Enabling is false, SHIP_BUILD is true, log to file is false, DBG is false
[System.out] (HTTPLog)-Thread-43420-520578202: SMARTBONDING_FEATURE_ENABLED is true
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] KnoxVpnUidStorageknoxVpnSupported API value returned is false
[System.out] KnoxVpnUidStorageknoxVpnSupported API value returned is false
View No If: 2
View == Null: 2
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] KnoxVpnUidStorageknoxVpnSupported API value returned is false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] KnoxVpnUidStorageknoxVpnSupported API value returned is false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[ListView] change accessibility focus position = 0
[skia] --- SkImageDecoder::Factory returned null
[skia] --- SkImageDecoder::Factory returned null
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
Realpos: 2       Position: 0
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
Realpos: 2       Position: 1
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
View No If: 2
View Not Null: 2
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] KnoxVpnUidStorageknoxVpnSupported API value returned is false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[skia] --- SkImageDecoder::Factory returned null
[skia] --- SkImageDecoder::Factory returned null
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
Realpos: 2       Position: 2
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
View No If: 3
View Not Null: 3
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] KnoxVpnUidStorageknoxVpnSupported API value returned is false
[System.out] KnoxVpnUidStorageknoxVpnSupported API value returned is false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[skia] --- SkImageDecoder::Factory returned null
[skia] --- SkImageDecoder::Factory returned null
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
Realpos: 3       Position: 0
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
View No If: 4
View Not Null: 4
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] KnoxVpnUidStorageknoxVpnSupported API value returned is false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[skia] --- SkImageDecoder::Factory returned null
[skia] --- SkImageDecoder::Factory returned null
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
Realpos: 4       Position: 2
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
View No If: 2
View Not Null: 2
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[skia] --- SkImageDecoder::Factory returned null
[skia] --- SkImageDecoder::Factory returned null
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
View No If: 1
View Not Null: 1
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
Realpos: 1       Position: 2
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
View No If: 0
View Not Null: 0
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] KnoxVpnUidStorageknoxVpnSupported API value returned is false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[skia] --- SkImageDecoder::Factory returned null
[skia] --- SkImageDecoder::Factory returned null
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
Realpos: 0       Position: 1
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
View No If: 2
View Not Null: 2
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[skia] --- SkImageDecoder::Factory returned null
[skia] --- SkImageDecoder::Factory returned null
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
View No If: 3
View Not Null: 3
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[skia] --- SkImageDecoder::Factory returned null
[skia] --- SkImageDecoder::Factory returned null
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
View No If: 4
View Not Null: 4
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[skia] --- SkImageDecoder::Factory returned null
[skia] --- SkImageDecoder::Factory returned null
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
Realpos: 4       Position: 2
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
View No If: 2
View Not Null: 2
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] KnoxVpnUidStorageknoxVpnSupported API value returned is false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[skia] --- SkImageDecoder::Factory returned null
[skia] --- SkImageDecoder::Factory returned null
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
View No If: 1
View Not Null: 1
[ViewRootImpl] ViewPostImeInputStage ACTION_DOWN
View No If: 0
View Not Null: 0
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[System.out] (HTTPLog)-Static: isSBSettingEnabled false
[skia] --- SkImageDecoder::Factory returned null
[skia] --- SkImageDecoder::Factory returned null

2条回答
我命由我不由天
2楼-- · 2019-08-10 22:19

Now i understand what you mean! This occurs,because we reusing rows(yes that a good thing to hold your views and dont recreate again and again).So problem with this part of code:

if (view == null)

To resolve this problem,you must to delete this block of code(where view is null),and after that will be OK,but you will lose some performance!(dont think that you have 1000 list items :), because w/o this post condition method GetView() will redraw always each ROW that is visible at current moment).
So in your case,i think it can be done.

Lets try my example,to see same stuff(with Toast):
Main.axml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <EditText
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:id="@+id/editText1" />
        <ListView
            android:minWidth="25px"
            android:minHeight="25px"
            android:layout_width="match_parent"
            android:layout_height="460dp"
            android:id="@+id/lst"
            android:layout_marginTop="50dp" />
        <Button
            android:text="Button"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:id="@+id/Test"
            android:layout_alignParentBottom="true" />
    </RelativeLayout>
</LinearLayout>  

MainActivity

 [Activity(Label = "TestStuff", MainLauncher = true, Icon = "@drawable/icon")]
    public class MainActivity : Activity
    {

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            SetContentView(Resource.Layout.Main);
            Window.SetSoftInputMode(SoftInput.AdjustNothing | SoftInput.AdjustPan);
            ListView lst = FindViewById<ListView>(Resource.Id.lst);
            Button btn = FindViewById<Button>(Resource.Id.Test);

            List<string> Data = new List<string>();
            Data.Add("Prosto GG 1");
            Data.Add("Prosto GG 2");
            Data.Add("Prosto GG 3");
            Data.Add("Prosto GG 4");
            Data.Add("Prosto GG 5");
            Data.Add("Prosto GG 6");
            Data.Add("Prosto GG 7");
            Data.Add("Prosto GG 8");
            Data.Add("Prosto GG 9");
            Data.Add("Prosto GG 10");
            Data.Add("Prosto GG 11");

            CustomAdapter cst = new CustomAdapter(Data, this);
            lst.Adapter = cst;

            btn.Click += (sender, e) => 
                {
                    Data.Add("ne prosto");
                    cst.NotifyDataSetChanged();
                };


        }
    }  

and finally,our new CustomAdapter(w/o block of code where View == null)

class CustomAdapter: BaseAdapter<string>
    {

    List<string> _Items;
    Context _context;
    public CustomAdapter(List<string> Items,Context context)
    {
        this._Items = Items;
        this._context = context;
    }


    public override long GetItemId(int position)
    {
        return position;
    }

public override View GetView(int position, View convertView, ViewGroup parent)
        {
            ServiceViewHolder holder = null;

            var view = convertView;

                holder = new ServiceViewHolder();
                view = LayoutInflater.From(_context).Inflate(Resource.Layout.ListItem, null);
                holder.Txt = view.FindViewById<TextView>(Resource.Id.txt);
                holder.PushME = view.FindViewById<Button>(Resource.Id.Push);
                holder.PushME.Click += (sender, e) => 
                    {

                        Toast.MakeText (_context, _Items [position] + " SHOWED", ToastLength.Short).Show ();
                        //holder.Txt.Text = holder.Txt.Text + "Izmenen najatiem" + position + " poziitii";
                    }

             holder.Txt.Text = _Items[position];

 return view;
  }  



 public override int Count
    {
        get
        {
            return _Items.Count;
        }
    }

    public override string this[int index]
    {
        get
        {
           return _Items[index];
        }
    }
    #endregion

}

public class ServiceViewHolder : Java.Lang.Object
{
    public Button PushME { get; set; }

    public TextView Txt { get; set; }

}

So that it!
Enjoy!

PS Also i would like to say,that beware with big size Data(e.g. 500-1000 items in List).

PPS But to be honest,there is no point to use ListView with huge item Data,because it's very expensive,for this you can use RecycleView ;)!

查看更多
走好不送
3楼-- · 2019-08-10 22:35

If your question is about the difference between Position and Realpos the reason is that Realpos is a class member which you set on every call to GetView.

So for example lets say you scroll your list, each new item updates this variable and all items share it, so even though the item you click index is 0, the last view that was added was index 2 and updated this variable.

查看更多
登录 后发表回答