2013-02-28 60 views
0

情况:我得到一个JSONObject包含用户的播放列表从服务器。我想在ListView中显示这​​些数据,在我的测试用例中有288个音频文件。 JSON被正确解析,大小等于288.我创建了一个帮助类并使用它的对象参数化了ArrayList。问题:我的ListView中正好有288个项目,但是艺术家 - 标题上升到索引13(不知道为什么),然后他们得到重复。所以我在列表中没有288个不同的条目,但我只有14个条目重复,直到列表结束。android - 从JSONArray填充ListView与数据

更新:我删除了if语句,它解决了问题,但RAM消耗增加了3MB。任何优化建议?

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); 

} 

的PlayListItem类:

 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; 
} 
    } 

适配器:

 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; 

} 

    } 
+0

覆盖getcount并返回data.length并覆盖getItem(int位置)并返回位置。确保您的数据列表数据具有全部288个元素。 – Raghunandan 2013-02-28 17:40:08

+0

你的意思是肯定data.size()。是的,它返回288 – Droidman 2013-02-28 17:47:46

+0

http://stackoverflow.com/questions/15109406/how-to-set-json-parsed-data-in-a-listview-and-then-adding-search-functionality-i/15109592#15109592 。检查这个链接。 – Raghunandan 2013-02-28 17:49:21

回答

1

我已经在你的getView method.Replace做了一些修改,并检查它。

@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; 
     } 
+0

就是这样!非常感谢 – Droidman 2013-02-28 18:12:28

1

如果将删除此行:

View row = convertView; 

,每一次膨胀的观点,然后这个问题将消失。 我也遇到了这个影响了几次,如下所述:

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

actualy我不知道为什么会这样,因为使用convertView建议。

更新:

试试这个:

@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; 

}

+0

+1作为答案。 – Raghunandan 2013-02-28 18:01:06

+0

这是一个缓慢且耗费内存的实现。当然不推荐。 – azertiti 2013-02-28 18:04:41

+0

刚刚尝试过,没有任何改变..我错过了别的东西吗? – Droidman 2013-02-28 18:07:02

2

在getView方法中,如果它是可回收的,那么您不再填充View。因此,一旦在屏幕之外滚动,它将开始显示旧的。您也没有设置/检索ViewHolder。请尝试以下实现(未测试)。

@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; 
} 
+0

谢谢。 Karan_Rana表示同样更快一点,所以我会接受他的回答。 Upvote给你。感谢您抽出时间 – Droidman 2013-02-28 18:13:23

1
 if (convertView == null)// if null 

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

进行这些更改。