我制作了一个自定义适配器,以便我可以创建自定义列表视图。自定义适配器接受我自己的RowItem类的ArrayList,并且应该填充我的活动中的列表视图。
当我尝试使用自定义适配器时,我的活动中没有任何内容。经过一些研究后,我怀疑它可能是我的适配器的getCount函数返回0,所以我添加了一些日志信息来检查它。
它显示的是,起初,我的getCount确实返回一个正值(100),但接下来的下一刻,它返回一个零,然后继续这样做,这意味着我的getView没有被调用,列表仍然是空的。
这是我的活动
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());
}
}
这是我的自定义适配器类
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
另外,如果我的setData函数没有在任何地方调用(在我的parseHtml或自定义适配器构造函数中),我的应用程序崩溃了。
有谁知道我做错了什么?感谢。
答案 0 :(得分:0)
尝试设置this.rows = rows;在你的setData方法中,你可以随时更新它。
请注意,您只在CustomAdapter的构造函数中设置this.rows,而当您执行setData时,您没有设置它。另外,调用clear();在setData中,正在清除this.rows列表,因为数组适配器包含对您在构造函数中通过super的列表的引用。