Android CustomAdapter getCount()首先返回正计数,然后立即返回0
我制作了一个自定义适配器,以便可以制作自定义列表视图。自定义适配器接收我自己的RowItem类的ArrayList,并在我的活动中填充我的列表视图 当我尝试使用自定义适配器时,活动中没有出现任何问题。经过一些研究,我怀疑可能是适配器的getCount函数返回了一个0,所以我添加了一些日志信息来检查它 它显示的是,一开始,我的getCount确实返回一个正值(100),但接下来,它返回一个零,并继续这样做,这意味着我的getView没有被调用,列表仍然为空 这是我的活动Android CustomAdapter getCount()首先返回正计数,然后立即返回0,android,android-adapter,custom-adapter,Android,Android Adapter,Custom Adapter,我制作了一个自定义适配器,以便可以制作自定义列表视图。自定义适配器接收我自己的RowItem类的ArrayList,并在我的活动中填充我的列表视图 当我尝试使用自定义适配器时,活动中没有出现任何问题。经过一些研究,我怀疑可能是适配器的getCount函数返回了一个0,所以我添加了一些日志信息来检查它 它显示的是,一开始,我的getCount确实返回一个正值(100),但接下来,它返回一个零,并继续这样做,这意味着我的getView没有被调用,列表仍然为空 这是我的活动 package com.e
package com.example.topsongsbyyear;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ListAdapter;
import android.widget.ListView;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.util.ArrayList;
public class SongList extends AppCompatActivity implements Response.ErrorListener, Response.Listener<String> {
String webUrl;
String year;
RequestQueue requestQueue;
StringRequest stringRequest;
RowItem row;
ListView list;
ArrayList<RowItem> rows;
ListAdapter customAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
year = getIntent().getStringExtra("year");
webUrl = "https://www.billboard.com/charts/year-end/" + year + "/hot-100-songs";
setContentView(R.layout.activity_song_list);
rows = new ArrayList<RowItem>();
list = (ListView) findViewById(R.id.all_list);
list.setAdapter(customAdapter);
requestQueue = Volley.newRequestQueue(this);
stringRequest = new StringRequest(Request.Method.GET, webUrl, this, this);
requestQueue.add(stringRequest);
requestQueue.start();
}
@Override
public void onErrorResponse(VolleyError error) {
Log.i("----------------", "onErrorResponse executed");
}
@Override
public void onResponse(String response){
int rank = 1;
Log.i("----------------", "onResponse executed");
Document doc = Jsoup.parse(response);
parseHtml(doc);
//call setData function in adapter
//in setData, save the data and call notifyDataSetChanged (adapter method), which updates list view
}
@Override
public void onPointerCaptureChanged(boolean hasCapture) {
}
public void parseHtml(Document doc){
ArrayList<String> songList = new ArrayList<>();
ArrayList<String> artistList = new ArrayList<>();
ArrayList<String> imageUrls = new ArrayList<>();
rows = new ArrayList<RowItem>();
Elements songs = doc.select(".ye-chart-item__title");
for(Element song : songs){
songList.add(song.text().toString());
}
Elements artists = doc.select(".ye-chart-item__artist");
for(Element artist : artists){
artistList.add(artist.text().toString());
}
Elements images = doc.select("div.ye-chart-item__image > img");
for (Element image : images) {
imageUrls.add(image.attr("src"));
}
for(int i = 0; i < songList.size(); i++){
RowItem row = new RowItem(Integer.toString(i+1), songList.get(i), artistList.get(i), imageUrls.get(i));
rows.add(row);
}
Log.i("----------------", "Just added to rows arrayList with songList size: " + songList.size() + " artistList size: " + artistList.size() + "and imageUrls size: " +imageUrls.size());
Log.i("----------------", "Just before setting making customAdapter instance with row count " + rows.size());
customAdapter = new CustomAdapter(this, R.layout.row_layout, rows);
list.setAdapter(customAdapter);
if (customAdapter instanceof CustomAdapter){
((CustomAdapter) customAdapter).setData(rows);
}
Log.i("----------------","Adapter set after html parsed, with row count " + rows.size());
}
}
此外,如果我的setData函数没有在任何地方调用(在我的parseHtml或自定义适配器构造函数中),我的应用程序就会崩溃
有人知道我做错了什么吗?谢谢。尝试设置此选项。行=行;在setData方法中,您将随时更新它
请注意,您只是在CustomAdapter的构造函数中设置this.rows,而在设置数据时,您并没有设置它。另外,调用clear();在setData中,正在清除this.rows列表,因为数组适配器在构造函数中持有对要通过super的列表的引用。
ArrayAdapter
为其数据集维护一个私有的列表
字段。当您在super
构造函数调用中传递rows
时,它的字段然后指向您的ArrayList
,即100项。到目前为止,一切顺利。但是,然后调用setData()
方法,该方法调用clear()ArrayAdapter
上的code>,它清除其列表
字段,但该字段指向您的行
列表
,因此它会被清除,随后的addAll()
调用只会将一个空的列表
添加到一个空的列表
,因此返回0。也许最简单的解决方案就是去掉ArrayList行代码>字段。。。。。。并让ArrayAdapter
处理列表
。您可以使用ArrayAdapter
的getItem()
方法代替所有的行.get()
调用,只需删除getCount()
覆盖,因为ArrayAdapter
将正确处理它。或者,扩展BaseAdapter
,这样你是唯一一个接触列表的人,并且确切地知道在哪里发生了什么。嘿,迈克,我听从了你的建议,摆脱了我的ArrayList,改为使用ArrayAdapter的getItem()方法,效果很好!我也不需要setData()方法,只需在构造函数中调用notifyDataSetChanged()。非常感谢你的帮助!嗨,马克。多亏了Mike M.的投入,我已经解决了这个问题。不过我还是很感激你的帮助!非常感谢。
package com.example.topsongsbyyear;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
public class CustomAdapter extends ArrayAdapter<RowItem> {
Context context;
ArrayList<RowItem> rows;
TextView songName;
TextView artist;
TextView rank;
ImageView image;
public CustomAdapter(@NonNull Context context, int resource, ArrayList<RowItem> rows) {
super(context, resource, rows);
this.rows = rows;
Log.i("--------------", "row filled with " + this.rows.size() + " elements");
notifyDataSetChanged();
//setData(rows);
}
public void setData(ArrayList<RowItem> rows){
clear();
addAll(rows);
Log.i("----------------", "setData called, cleared and then addAll(rows) with row count: " + rows.size());
notifyDataSetChanged();
}
@Override
public int getCount() {
Log.i("----------------", "CustomAdapter getCount called, returning rows.size() which is: " + rows.size());
return rows.size();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.i("---------------", "entered getView function");
LayoutInflater inflater = LayoutInflater.from(getContext());
View customView = convertView;
if (convertView == null)
customView = inflater.inflate(R.layout.row_layout, parent, false);
//setData(rows);
String singleSong = rows.get(position).getSong();
String singleArtist = rows.get(position).getArtist();
String singleRank = rows.get(position).getRank();
String singleImage = rows.get(position).getPicUrl();
songName = (TextView) customView.findViewById(R.id.title);
artist = (TextView) customView.findViewById(R.id.artist);
rank = (TextView) customView.findViewById(R.id.rank);
Log.i("----------------", "ADDED: " + singleRank + " " + singleSong + " by " + singleArtist +" TO LIST");
image = (ImageView) customView.findViewById(R.id.list_image);
songName.setText(singleSong);
artist.setText(singleArtist);
rank.setText(singleRank);
Glide.with(context).
load(singleImage).
into(image);
return customView;
}
}
05-10 19:49:54.610 29217-29217/com.example.topsongsbyyear I/----------------: onResponse executed
05-10 19:49:54.657 29217-29217/com.example.topsongsbyyear I/----------------: Just added to rows arrayList with songList size: 100 artistList size: 100and imageUrls size: 100
05-10 19:49:54.658 29217-29217/com.example.topsongsbyyear I/----------------: Just before setting making customAdapter instance with row count 100
05-10 19:49:54.658 29217-29217/com.example.topsongsbyyear I/--------------: row filled with 100 elements
05-10 19:49:54.658 29217-29217/com.example.topsongsbyyear I/----------------: CustomAdapter getCount called, returning rows.size() which is: 100
CustomAdapter getCount called, returning rows.size() which is: 100
05-10 19:49:54.659 29217-29217/com.example.topsongsbyyear I/----------------: CustomAdapter getCount called, returning rows.size() which is: 0
05-10 19:49:54.659 29217-29217/com.example.topsongsbyyear I/chatty: uid=10086(com.example.topsongsbyyear) identical 2 lines
05-10 19:49:54.660 29217-29217/com.example.topsongsbyyear I/----------------: CustomAdapter getCount called, returning rows.size() which is: 0
setData called, cleared and then addAll(rows) with row count: 0
CustomAdapter getCount called, returning rows.size() which is: 0
CustomAdapter getCount called, returning rows.size() which is: 0
Adapter set after html parsed, with row count 0
05-10 19:49:54.675 29217-29217/com.example.topsongsbyyear I/----------------: CustomAdapter getCount called, returning rows.size() which is: 0
05-10 19:49:54.681 29217-29217/com.example.topsongsbyyear I/----------------: CustomAdapter getCount called, returning rows.size() which is: 0
05-10 19:49:54.842 29217-29217/com.example.topsongsbyyear I/----------------: CustomAdapter getCount called, returning rows.size() which is: 0
05-10 19:49:54.844 29217-29217/com.example.topsongsbyyear I/----------------: CustomAdapter getCount called, returning rows.size() which is: 0
05-10 19:49:55.057 29217-29241/com.example.topsongsbyyear I/chatty: uid=10086(com.example.topsongsbyyear) RenderThread identical 2 lines