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;

}

    }
7
  • override getcount and return data.length and override getItem(int position) and return position. Make sure your arraylist data has all the 288 elements. Commented Feb 28, 2013 at 17:40
  • u mean for sure data.size(). Yes it returns 288 Commented Feb 28, 2013 at 17:47
  • stackoverflow.com/questions/15109406/…. Check this link. Commented Feb 28, 2013 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. Commented Feb 28, 2013 at 17:52
  • are you getting the first 14 items correctly?? Commented Feb 28, 2013 at 17:53

4 Answers 4

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;
}
Sign up to request clarification or add additional context in comments.

1 Comment

thank you. Karan_Rana said the same a bit faster so I'll accept his answer. Upvote for you. Thanks for taking time
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;
        }

Comments

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.

Comments

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;

}

4 Comments

This is a slow and memory consuming implementation. Certainly not recommended.
just tried that, nothing changed.. Did I miss something else?
as I said using the convertView is recommended even by Romain Guy on the UI development presentation that can be seen here: youtube.com/watch?v=N6YdwzAvwOA but this is the only way i managed to get around this issue.
yeah I did watch this video a while ago

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.