2

Hi I am new to this android. I am just confused by base adapter. My problem is that consider In an array I have 10 items(from 0 to 9). In the getview() option of baseadapter I am displaying this in textview. But after executing 5 times correctly once again the position is resetting to 0. So items are repeating twice.

This is my adapterclass:

public class ListViewwithimageAdapter extends BaseAdapter
{
    private static Context contxt;
    final String URL = "http://xxxx.in/SSDAA.xml";

    final String[] kickerimage = new String[150];

    ListViewwithimageAdapter(Context conxt)
    {
//      System.out.println("inside cons");
        this.contxt=conxt;
    }
    {

    }
    public String[] getelement()
    {
//      System.out.println("Insid getelement");
         ArrayList<String> menuItems = new ArrayList<String>();
          TaplistingParser parser = new TaplistingParser();
          String xml= parser.getXmlFromUrl(URL);
          Document doc=parser.getDomElement(xml);        
//        System.out.println("sssss="+doc);
          NodeList nl=doc.getElementsByTagName("article");
          final String[] url= new String[nl.getLength()];

//        String headings = null;
          for(int i=0; i < nl.getLength(); i++ )
          {
//            System.out.println("i="+i);
            HashMap<String, String> map = new HashMap<String, String>();
            Element e = (Element) nl.item(i);
//          map.put("Title", parser.getValue(e, "title"));
//          map.put("Date", parser.getValue(e, "create_date"));         
            url[i]=parser.getValue(e, "url");
//          System.out.println("b4 kick");
//          System.out.println("value="+parser.getValue(e, "title"));
            kickerimage[i]=parser.getValue(e, "kickerimage");
//          System.out.println("after kick");
//          System.out.println("kick="+kickerimage[i]);
            menuItems.add(parser.getValue(e, "title"));          
          }  
//         System.out.println("b4 items array");
           String[] itemsarray = new String[menuItems.size()];
//         System.out.println("subbu");
           itemsarray=menuItems.toArray(itemsarray);
//         System.out.println("subbu1");
//         System.out.println("in last");
           return itemsarray;
    }
    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return getelement().length;
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return getelement()[position];
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
//      System.out.println("pos in id="+position);
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) 
    {
        // TODO Auto-generated method stub
        System.out.println("pos in id="+position);                     ------------------->This soutline gives output as(0,1,2,3,4,5,0).
         Bitmap bitmap = DownloadImage(
                 kickerimage[position] );
        LayoutInflater inflater = (LayoutInflater) contxt
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View listView;
        if (convertView == null) 
        {
            listView = new View(contxt);             

            listView = inflater.inflate(R.layout.homelistrow, null); 
            System.out.println("pos="+position);
            System.out.println("item="+getItem(position));

            TextView textView = (TextView) listView
                    .findViewById(R.id.name_label);
            textView.setText(getelement()[position]);

            ImageView imageView = (ImageView) listView
                    .findViewById(R.id.icon);
            imageView.setImageBitmap(bitmap);
        }
        else        
        {
            listView = (View) convertView;
        } 
        return listView;

    }

    private Bitmap DownloadImage(String URL)
    {        
//      System.out.println("image inside="+URL);
        Bitmap bitmap = null;
        InputStream in = null;        
        try {
            in = OpenHttpConnection(URL);
            bitmap = BitmapFactory.decodeStream(in);
            in.close();
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
//        System.out.println("image last");
        return bitmap;                
    }
    private InputStream OpenHttpConnection(String urlString)
            throws IOException
            {
                InputStream in = null;
                int response = -1;

                URL url = new URL(urlString);
                URLConnection conn = url.openConnection();

                if (!(conn instanceof HttpURLConnection))                    
                    throw new IOException("Not an HTTP connection");

                try{
                    HttpURLConnection httpConn = (HttpURLConnection) conn;
                    httpConn.setAllowUserInteraction(false);
                    httpConn.setInstanceFollowRedirects(true);
                    httpConn.setRequestMethod("GET");
                    httpConn.connect();

                    response = httpConn.getResponseCode();                
                    if (response == HttpURLConnection.HTTP_OK) {
                        in = httpConn.getInputStream();                                
                    }                    
                }
                catch (Exception ex)
                {
                    throw new IOException("Error connecting");            
                }
                return in;    
    }

}

My Homerowlist:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <ImageView
        android:id="@+id/icon"
        android:layout_width="80dp"
        android:layout_height="80dp"        
        android:paddingLeft="10dp"
        android:paddingRight="10dp" />

    <TextView
        android:id="@+id/name_label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/icon"
        android:paddingBottom="10dp"
        android:textColor="#ffffff"
        android:textSize="16dp" />


</RelativeLayout>

In my activity setting adapter:

 ListView l2= (ListView)findViewById(R.id.list);
          ListViewwithimageAdapter adapter = new ListViewwithimageAdapter(this);
          l2.setAdapter(adapter);

Please help me. Thanks in advance.

Subburaj
  • 5,114
  • 10
  • 44
  • 87
  • What are you using the adapter for? ListView? – Andy Nov 12 '12 at 07:15
  • thanks Andy..Ya for listview – Subburaj Nov 12 '12 at 07:16
  • Listen to @Ridcully I was going to say not to call getCount() in getView as its doing a lot of work in the short amount of time it takes to replace everything on a recycled View. Change your array design to hold everything it needs immediately to make it all a lot faster and more efficient. – Andy Nov 12 '12 at 08:14

2 Answers2

1

I think you didn't completely grab the concept of view-reuse done in the adapters. What the adapter together with the listview does is, that at first it creates a view for every list-item you can see. When you begin to scroll down, the topmost view is no longer visible and the listview needs a new one for the new item coming into view. Now instead of freeing the vanished view and allocating a completely new view, the adapter gives you the vanished view (as convertView) so instead of allocating a new one (which is relativly time costly) you just have to convert this view to make it right for the item at the given position. So in your case, when you get a non-null convertView do not return it un-changed (because then it will look the same as the one just vanished at the top), but instead tweak it to show the item at the given position, i.e. set it's image and text accordingly.

Btw. you should not call the costly getelement() that often. Instead, just call it in the adapter's constructor and store the returned array for later access in getCount(), getView() etc.

Ridcully
  • 23,362
  • 7
  • 71
  • 86
  • haha, thanks for the clarification. I know I didn't go over that part. But I posted a link for him on my answer :) hopefully he will look at it. – Andy Nov 12 '12 at 08:11
  • Yes, it's a classic. Took me a while too, to understand, but it's logical when one keeps Android's performance ambitions in mind. – Ridcully Nov 12 '12 at 08:13
  • I got a valid point form u Ridcully..Now i called the getelement() in constructor..Now the loading time is very less and the app is smooth compared to b4..thanks a lot..\ – Subburaj Nov 12 '12 at 08:18
0

Using any type of Adapter with ListView is tricky business. Your issue essentially stems from the fact that ListView reuses the View you inflate, or at least a few of them. So it'll make like 7 or whatever, and then as you scroll literally reuse a View that is now off the screen. This is the reason you are suppose to check if convertView is null. I see a few things off, so I will tell you what to move around.

The main issue you are having is to erase everything in your View that you get from convertView.

public View getView(int position, View convertView, ViewGroup parent) 
{
    // TODO Auto-generated method stub
    System.out.println("pos in id="+position);                     
     Bitmap bitmap = DownloadImage(
             kickerimage[position] );


    if (convertView == null) 
    {
        //this should only ever run if you do not get a view back            
        LayoutInflater inflater = (LayoutInflater) contxt
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.homelistrow, null); 

    }
    TextView textView = (TextView) convertView
                .findViewById(R.id.name_label);
        textView.setText(getelement()[position]);

        ImageView imageView = (ImageView) convertView
                .findViewById(R.id.icon);
        imageView.setImageBitmap(bitmap);

    return convertView;

}

So where you see holder.removeAllViews();, thats key. ListView makes no guarantees how many times getView() is called (which is why you see position change a lot and even duplicate). And it could be called on something you already called before, hence the duplicate entries. Remember, Views are recycled. Like imagine a whole row just being reused. So whatever was in it before will still be there, which is why you must delete everything and start fresh every time. You may have noticed I also moved things around. Look it over to understand why. No reason to create a new View when you can use convertView right, well only if its null. Also notice that you are only going to removeAllView's only if convertView is not null. Everything else should always run regardless.

Edit

Ok, so you do not need to remove all the views within the RelativeLayout since every time it runs, you will be replacing it. Try out what I just changed. It should work.

Check out this link on a video by the guy who created the ListView framework: World of ListView

Andy
  • 10,553
  • 21
  • 75
  • 125
  • This line LinearLayout holder = (LinearLayout)convertView.findViewById(R.id.container_view);-------->actually i am using listview.Whether i have to use that???Andy – Subburaj Nov 12 '12 at 07:41
  • Post that `R.layout.homelistrow` xml up please. And you are suppose to set `ListViewWithimageAdapter` to a `ListView` somewhere. I never see `setAdapter` called. Like show me in your Activity where you are setting `ListView` with the `ListViewWithimageAdapter` adapter. – Andy Nov 12 '12 at 07:45
  • I just made a quick edit. Removes the Linerlayout, but everything else should remain the same. – Andy Nov 12 '12 at 07:56
  • In this line LinearLayout holder = (LinearLayout)convertView.findViewById(R.id.container_view); container_view is showing error. – Subburaj Nov 12 '12 at 07:56
  • Oh that was an example. I just deleted that section because I did not know what you called yours. Now that I know I took out that section. Re-run it after you do – Andy Nov 12 '12 at 07:57
  • Look at my revised code. I deleted everything to do with `holder`. – Andy Nov 12 '12 at 08:00
  • Andy Job is done..Really thanks a lot..Thanks andy..I tried to upvote but i didn't have that much reputation.. – Subburaj Nov 12 '12 at 08:04
  • Haha. Don't worry about it. Glad I could help :) good luck with the app. And I will post a link to a video about `ListView`. Watch it so you can understand it a bit more. Cheers! – Andy Nov 12 '12 at 08:08