【问题标题】:android - populating ListView with data from JSONArrayandroid - 使用 JSONArray 中的数据填充 ListView
【发布时间】:2013-03-01 02:14:23
【问题描述】:

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

更新:我删除了 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;

}

    }

【问题讨论】:

  • 覆盖 getcount 并返回 data.length 并覆盖 getItem(int position) 并返回位置。确保您的 arraylist 数据包含所有 288 个元素。
  • 你的意思肯定是 data.size()。是的,它返回 288
  • 在上面的链接中我使用了 hashmap 。因此,每次您获得 jsondata 时,都将其添加到 hashmap 并将该 hashmap 放入列表中。所以arraylist位置包含第一个json数据的所有数据,包括艺术家和标题。我相信你可以通过链接解决问题。
  • 前 14 项是否正确??

标签: android android-listview


【解决方案1】:

在 getView 方法中,如果 View 是回收的,则不会再次填充 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;
}

【讨论】:

  • 谢谢。 Karan_Rana 说得快一点,所以我会接受他的回答。为你点赞。感谢您抽出宝贵时间
【解决方案2】:

我对您的 getView 方法进行了一些修改。替换它并检查它。

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

【讨论】:

    【解决方案3】:
          if (convertView == null)// if null
    
           {
            convertView = mInflater.inflate(R.layout.list, null);//inflate view
           } else 
           {
            holder = (ViewHolder) convertView.getTag();// set tag to holder.
           }
    

    进行这些更改。

    【讨论】:

      【解决方案4】:

      如果您要删除此行:

       View row = convertView;
      

      每次都放大视图,然后这个问题就会消失。 我也遇到过几次这种影响,如下所述:

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

      其实我不知道为什么会这样,因为推荐使用 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;
      

      }

      【讨论】:

      • 这是一个缓慢且消耗内存的实现。当然不推荐。
      • 刚刚试了一下,没有任何改变。我错过了什么吗?
      • 正如我所说,即使 Romain Guy 在 UI 开发演示文稿中也推荐使用 convertView,可以在此处看到:youtube.com/watch?v=N6YdwzAvwOA 但这是我设法解决此问题的唯一方法。跨度>
      • 是的,我之前确实看过这个视频
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多