Сделать мой CustomView ArrayAdapter ListView расширяемым?

У меня есть собственный ListView, который я заполняю своим собственным ArrayAdapter. Я читаю и анализирую данные json по URL и заполняю ListView этим. Это прекрасно работает, когда я читаю первый файл. Теперь я хочу иметь возможность добавлять больше данных (старые сообщения) в мой ListView. Я добавил кнопку "Загрузить еще" в качестве нижнего колонтитула в ListView, когда я загрузил новые данные и попытался прокрутить их, я получил эту ошибку:

java.lang.IndexOutOfBoundsException: неверный индекс 25, размер 25

Сначала я вообще не понимал, почему это так, теперь я понимаю, что мой ListView не расширяется. Когда я ищу в Google расширяемые ListView, пользовательские адаптеры расширяют BaseExpandableListAdapter, но я не уверен, как реализовать это в моем приложении. Мой настраиваемый адаптер массива определяется следующим образом:

private class StreamAdapter extends ArrayAdapter<Message>

Сообщение является одним из моих классов.

Вот как я отображаю данные:

private void DisplayData() {
    // If the request was successfull then notify the adapter to display the data
    if(success) {

        if(dataAdapter.isEmpty())
        {
            dataAdapter.addAll(dataList);
            dataAdapter.notifyDataSetChanged();
        }
        // If the listview isn't empty we want to erase what's there and then add the older posts to display
        else
        {
            /** Add currently displayed messages to a temporary arraylist, clear the listview, then add both arraylists in the correct order **/
            int size = messageList.getTop();
            ArrayList<Message> temp = new ArrayList<Message>();

            for(int i = 0; i < size; i++)
            {
                temp.add(dataAdapter.getItem(i));
            }
            dataAdapter.clear();
            temp.addAll(dataList);

            dataAdapter.addAll(temp);
            dataAdapter.notifyDataSetChanged();
        }
    }
}

Вся вещь temp-ArrayList была единственным способом, которым я мог придумать, чтобы получить недавно загруженные данные (но самые старые сообщения) внизу списка, а не вверху.

Есть ли способ легко сделать мой ListView расширяемым или мне нужно переписать весь мой класс StreamAdapter?

Кристина

РЕДАКТИРОВАТЬ: Вот код для моего класса StreamAdapter, но я не учел некоторые части, так как я уверен, что это не актуально и просто добавляет к куче кода.

закрытый класс StreamAdapter расширяет ArrayAdapter {

public StreamAdapter(Context context, int textViewResourceId, ArrayList<Message> dataList) 
{
    super(context,textViewResourceId, dataList);
}

private class ViewHolder {
    ImageView thumbnail;
    TextView display_name;
    TextView username;
    TextView created_at;
    TextView text;
    ImageView comments;
    TextView nr_comments;
    @SuppressWarnings("unused")
    ImageView like;
    TextView nr_likes;
    @SuppressWarnings("unused")
    ImageView starred;
    TextView nr_starred;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder = null;

    if(convertView == null)
    {
        LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = vi.inflate(R.layout.data_row, null);


        holder = new ViewHolder();
        holder.thumbnail = (ImageView) convertView.findViewById(R.id.thumbnail);
        holder.display_name = (TextView) convertView.findViewById(R.id.display_name);               
        holder.username = (TextView) convertView.findViewById(R.id.username);
        holder.created_at = (TextView) convertView.findViewById(R.id.created_at);
        holder.text = (TextView) convertView.findViewById(R.id.text);
        holder.comments = (ImageView) convertView.findViewById(R.id.comments);
        holder.nr_comments = (TextView) convertView.findViewById(R.id.nr_comments);
        holder.like = (ImageView) convertView.findViewById(R.id.like);
        holder.nr_likes = (TextView) convertView.findViewById(R.id.nr_likes);
        holder.starred = (ImageView) convertView.findViewById(R.id.starred);
        holder.nr_starred = (TextView) convertView.findViewById(R.id.nr_starred);

        convertView.setTag(holder);
    }
    else
    {
        holder = (ViewHolder) convertView.getTag();
    }

    final Message data = dataList.get(position);
    holder.thumbnail.setImageDrawable(getResources().getDrawable(R.drawable.owl_thumbnail));
    holder.display_name.setText(data.created_by.getDisplay_name());
    holder.username.setText("@"+data.created_by.getUsername());
    holder.created_at.setText(data.getCreated_at());
    holder.nr_comments.setText(Integer.toString(data.getComments().length));
    holder.nr_likes.setText(Integer.toString(data.getLiked_by().length));
    holder.nr_starred.setText(Integer.toString(data.getStarred_by().length));


    // Code to make certain text in the text-textview clickable

    // Clickhandler for the username (display_name)
    holder.display_name.setOnClickListener(new OnClickListener() {
        // Code
    });

    // Clickhandler for comments
    holder.comments.setOnClickListener(new OnClickListener() {
        //Code
    });

    return convertView;
}

}

3 ответа

Решение

Вместо добавления новых данных в элементы адаптера попробуйте получить ссылку на ваш список данных из адаптера и добавить эти данные в него, например:

private class StreamAdapter extends ArrayAdapter {

private  ArrayList<Message> dataList;
public StreamAdapter(Context context, int textViewResourceId, ArrayList<Message> dataList) 
{
    super(context,textViewResourceId, dataList);
    this.dataList=dataList;
}

public  ArrayList<Message> getDataList(){
   return dataList;
}

public void setDataList(ArrayList<Message> dataList){
   this.dataList=dataList;
}

...
...

}

И когда вы обновите его

private void DisplayData() {
    // If the request was successfull then notify the adapter to display the data
    if(success) {

            ArrayList<Message> temp = dataAdapter.getDataList();

            for(int i = 0; i < dataList.size(); i++)
            {
                temp.add(i,dataList.get(i));
            }

            dataAdapter.notifyDataSetChanged();
        }
}

Это должно сработать, попробуйте и дайте мне знать.

Также переопределить следующую функцию внутри адаптера

@Override
    public int getCount() {
        return dataList.size();
    }

РЕДАКТИРОВАТЬ

private void DisplayData() {
    // If the request was successfull then notify the adapter to display the data
    if(success) {

            ArrayList<Message> temp = dataAdapter.getDataList();
            dataList.addAll(temp);
            dataAdapter.setDataList(dataList);

            dataAdapter.notifyDataSetChanged();
        }
}

РЕДАКТИРОВАТЬ 2

private void DisplayData() {
    // If the request was successfull then notify the adapter to display the data
    if(success) {

            ArrayList<Message> temp = dataAdapter.getDataList();
            temp.addAll(dataList);
            dataAdapter.notifyDataSetChanged();
        }
}

Нет, вы не должны использовать ExpandableListAdapter, и вам не нужно предоставлять новую реализацию адаптера. Исключение, которое вы получаете, вероятно, связано с плохой обработкой массива, как вы уже догадались. У меня была похожая проблема, но я использовал адаптеры с Cursor (запрашивающим базу данных), поэтому я думаю, что notifydataSetChanged() должно быть достаточно, чтобы адаптер перезагрузил данные и отобразил их после того, как адаптер был заполнен дополнительными данными.

ExpandableListAdapter используется, когда вам нужно отобразить данные способом PARENT -> CHILDREN, поэтому с ExpandableListView вы видите список родительских элементов, каждый из которых имеет несколько дочерних элементов, каждый родительский элемент раскрывается / сворачивается (и, таким образом, показывает / скрывает дочерние элементы), когда вы нажмите здесь.

Попробуй заменить

int size = messageList.getTop();

с

int size = dataAdapter.getCount();
Другие вопросы по тегам