0

Situation: I'm getting a JSONObject containing user's playlist from the server. I want to display this data in a ListView, there are 288 audio files in my test case. The JSON is parsed correctly, the size equals to 288. I created a help class and parametrized the ArrayList with its Objects. The problem: there're exactly 288 items in my ListView BUT the correct entries Artist - Title go up to index 13 (don't know why) and then they get repeated. So I don't have 288 different entries in the List, but I have only 14 entries which are repeated until the end of the List.

UPDATE: I removed the if statement and it solved the issue but RAM consumption has increased by 3MB. Any suggestions for optimizing?

   public class AudioList extends ListActivity {

private ListView lv;
private JSONObject usersPlaylist, singleJSONItem;
private JSONArray responseJSONArray;
private SharedPreferences prefs;
private PlaylistItem audioList;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_audio_list);
    init();

    ArrayList<PlaylistItem> playlist = new ArrayList<PlaylistItem>();
    try {
        usersPlaylist = Utils.retrieveJsonObjectFromUrl(new URL(
                APP_CONSTANTS.REQUEST_AUDIO_LIST(prefs)), this);
        responseJSONArray = usersPlaylist.getJSONArray("response");

        for (int i = 0; i < responseJSONArray.length(); i++) {
            singleJSONItem = responseJSONArray.getJSONObject(i);
            audioList = new PlaylistItem(singleJSONItem);
            playlist.add(audioList); 
        }

        Toast.makeText(getApplicationContext(),
                Integer.toString(playlist.size()), Toast.LENGTH_LONG)
                .show(); //there are 288 entries, JSONArray parsed correctly

    } catch (MalformedURLException e) {

        e.printStackTrace();
    } catch (JSONException e) {

        e.printStackTrace();
    } catch (IOException e) {

        e.printStackTrace();
    }

    AudioListAdapter adapter = new AudioListAdapter(this,
            R.layout.playlist_item, playlist);
    lv.setAdapter(adapter);

}

private void init() {
    lv = getListView();
    lv.setTranscriptMode(0x00000000);
    lv.setDividerHeight(1);
    lv.setSmoothScrollbarEnabled(true);
    prefs = PreferenceManager.getDefaultSharedPreferences(this);

}

The PlayListItem class:

     public class PlaylistItem {

private String artist, title;
private JSONObject obj;

public PlaylistItem(JSONObject obj) {
    this.obj = obj;
}
public PlaylistItem(){

}

public String getArtist() {
    try {
        artist = obj.getString("artist");
    } catch (JSONException e) {

        e.printStackTrace();
    }
    return artist;

}

public String getTitle() {
    try {
        title = obj.getString("title");
    } catch (JSONException e) {

        e.printStackTrace();
    }
    return title;
}
    }

The adapter:

     public class AudioListAdapter extends ArrayAdapter<PlaylistItem> {

private Context context;
private int layoutResourceId;
private PlaylistItem aud;
private ArrayList<PlaylistItem> data = null;

public AudioListAdapter(Context context, int layoutResourceId,
        ArrayList<PlaylistItem> data) {
    super(context, layoutResourceId, data);
    this.layoutResourceId = layoutResourceId;
    this.context = context;
    this.data = data;

}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View row = convertView;
    ViewHolder holder = new ViewHolder();
    aud = data.get(position);
            //it's giving a CORRECT position if I hardcode the index, like data.get(99);
    if (row == null) {

        LayoutInflater inflater = ((Activity) context).getLayoutInflater();
        row = inflater.inflate(layoutResourceId, parent, false);
        holder.play = (Button) row.findViewById(R.id.btn_list_play);
        holder.imgSaved = (ImageView) row
                .findViewById(R.id.img_list_audio_saved);
        holder.tvArtist = (TextView) row
                .findViewById(R.id.tvListItemArtist);
        holder.tvTitle = (TextView) row.findViewById(R.id.tvListItemSong);

        holder.tvArtist.setText(aud.getArtist());
        holder.tvTitle.setText(aud.getTitle());

    }

    return row;
}

static class ViewHolder {
    Button play;
    ImageView imgSaved;
    TextView tvArtist, tvTitle;

}

    }
Droidman
  • 11,485
  • 17
  • 93
  • 141
  • override getcount and return data.length and override getItem(int position) and return position. Make sure your arraylist data has all the 288 elements. – Raghunandan Feb 28 '13 at 17:40
  • u mean for sure data.size(). Yes it returns 288 – Droidman Feb 28 '13 at 17:47
  • http://stackoverflow.com/questions/15109406/how-to-set-json-parsed-data-in-a-listview-and-then-adding-search-functionality-i/15109592#15109592. Check this link. – Raghunandan Feb 28 '13 at 17:49
  • in the above link i have used hashmap . so every time u get jsondata add it to hashmap and that hashmap is put to a list. so arraylist position contains all data of 1st json data with artist and title. I am sure u can work ur way around with the link. – Raghunandan Feb 28 '13 at 17:52
  • are you getting the first 14 items correctly?? – Raghunandan Feb 28 '13 at 17:53
  • yes, they are different. Just noticed: I added a toast which shows position value to getView() method and it immediately counts up to 13. Then this value only increases when I scroll down the list.. – Droidman Feb 28 '13 at 17:58
  • Emil Adj has the answer for you. I just missed out. That has to work. I don't see much of a error in your code. It will work just remove View row = convertView and instead of if (row == null) change it to if (convertView==null) . – Raghunandan Feb 28 '13 at 18:03

4 Answers4

2

In getView method you are not populating the View again if it's a recycled one. Therefore once you scroll outside the screen it will start displaying the old ones. You are also not setting/retrieving the ViewHolder. Please try the following implementation (not tested).

@Override
public View getView(int position, View convertView, ViewGroup parent) {
   View row = convertView;
   ViewHolder holder = null;
   aud = data.get(position);
        //it's giving a CORRECT position if I hardcode the index, like data.get(99);
   if (row == null) {
       holder = new ViewHolder();
       LayoutInflater inflater = ((Activity) context).getLayoutInflater();
       row = inflater.inflate(layoutResourceId, parent, false);
       holder.play = (Button) row.findViewById(R.id.btn_list_play);
       holder.imgSaved = (ImageView) row
            .findViewById(R.id.img_list_audio_saved);
       holder.tvArtist = (TextView) row
            .findViewById(R.id.tvListItemArtist);
       holder.tvTitle = (TextView) row.findViewById(R.id.tvListItemSong);          
       row.setTag(holder);
} else {
    holder = (ViewHolder)row.getTag();
}
holder.tvArtist.setText(aud.getArtist());
holder.tvTitle.setText(aud.getTitle());

return row;
}
azertiti
  • 3,150
  • 17
  • 19
  • thank you. Karan_Rana said the same a bit faster so I'll accept his answer. Upvote for you. Thanks for taking time – Droidman Feb 28 '13 at 18:13
1

If you will remove this line:

 View row = convertView;

and inflate the view every time, then this problem will go away. I did as well encountered this affect a couple of times as described here:

How to save state of changed ImageView in Listview row, after it' has disappeared from screen?

actualy i dont know why this happens because using the convertView is recommended.

Update:

try this one:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row;
ViewHolder holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(layoutResourceId, parent, false);
holder.play = (Button) row.findViewById(R.id.btn_list_play);
holder.imgSaved = (ImageView) row.findViewById(R.id.img_list_audio_saved);
holder.tvArtist = (TextView) row.findViewById(R.id.tvListItemArtist);
holder.tvTitle = (TextView) row.findViewById(R.id.tvListItemSong);
holder.tvArtist.setText(aud.getArtist());
holder.tvTitle.setText(aud.getTitle());

return row;

}

Community
  • 1
  • 1
Emil Adz
  • 40,709
  • 36
  • 140
  • 187
  • This is a slow and memory consuming implementation. Certainly not recommended. – azertiti Feb 28 '13 at 18:04
  • just tried that, nothing changed.. Did I miss something else? – Droidman Feb 28 '13 at 18:07
  • as I said using the convertView is recommended even by Romain Guy on the UI development presentation that can be seen here: http://www.youtube.com/watch?v=N6YdwzAvwOA but this is the only way i managed to get around this issue. – Emil Adz Feb 28 '13 at 18:09
  • yeah I did watch this video a while ago – Droidman Feb 28 '13 at 18:22
1

I have done some modifications in your getView method.Replace it and check it.

  @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View row = convertView;
            ViewHolder holder;
            aud = data.get(position);
                    //it's giving a CORRECT position if I hardcode the index, like data.get(99);
            if (row == null) {
                holder = new ViewHolder();
                LayoutInflater inflater = ((Activity) context).getLayoutInflater();
                row = inflater.inflate(layoutResourceId, parent, false);
                holder.play = (Button) row.findViewById(R.id.btn_list_play);
                holder.imgSaved = (ImageView) row.findViewById(R.id.img_list_audio_saved);
                holder.tvArtist = (TextView) row .findViewById(R.id.tvListItemArtist);
                holder.tvTitle = (TextView) row.findViewById(R.id.tvListItemSong);
                row.setTag(holder);
        }
    else
    {
                    holder = (ViewHolder ) row.getTag();

    }
                holder.tvArtist.setText(aud.getArtist());
                holder.tvTitle.setText(aud.getTitle());



            return row;
        }
Karan_Rana
  • 2,813
  • 2
  • 26
  • 35
1
      if (convertView == null)// if null

       {
        convertView = mInflater.inflate(R.layout.list, null);//inflate view
       } else 
       {
        holder = (ViewHolder) convertView.getTag();// set tag to holder.
       }

Make those changes.

Raghunandan
  • 132,755
  • 26
  • 225
  • 256