I'm trying to download XML data with Retrofit and parse it with Simple and then load it into a ListView.
Unfortunately downloaded data won't appear on screen. Could someone tell me where is the problem, please?
This is my model:
@Root(name = "item")
public class Article {
@Element(name = "title")
private String title;
@Element(name = "author")
private String author;
@Element(name = "description")
private String description;
The code for interface:
public interface Service {
@GET("/rss/news")
public void getArticle(Callback<List<Article>> callback);
}
The code for fragment:
public class ArticlePreviewFragment extends Fragment {
protected ArticlePreviewAdapter adapter;
protected List<Article> previewList;
private ListView listView;
public ArticlePreviewFragment() {}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
previewList = new ArrayList<>();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_article_preview, container, false);
listView = (ListView) view.findViewById(R.id.previewList);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
adapter = new ArticlePreviewAdapter(getActivity(), previewList);
listView.setAdapter(adapter);
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint("http://muse.mu")
.setConverter(new SimpleXMLConverter())
.build();
Service service = restAdapter.create(Service.class);
Callback<List<Article>> callback = new Callback<List<Article>>() {
@Override
public void success(List<Article> articles, Response response) {
adapter.clear();
adapter.addAll(articles);
adapter.notifyDataSetChanged();
}
@Override
public void failure(RetrofitError error)
};
service.getArticle(callback);
}
}
I'm using the converter found here - I've copied it into my project retrofit/converter/SimpleXMLConverter.java
Lastly, the code for adapter:
public class ArticlePreviewAdapter extends ArrayAdapter<Article> {
List<Article> articlePreviewItems;
public ArticlePreviewAdapter(Activity activity, List<Article> articlePreviewItems) {
super(activity, R.layout.item_article_preview, articlePreviewItems);
this.articlePreviewItems = articlePreviewItems;
}
private static class ViewHolder {
TextView articlePreviewTitle;
TextView articlePreviewAuthor;
TextView articlePreviewDescription;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
Article articlePreviewItem = getItem(position);
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.item_article_preview, parent, false);
viewHolder.articlePreviewTitle = (TextView) convertView.findViewById(R.id.articleTitle);
viewHolder.articlePreviewAuthor = (TextView) convertView.findViewById(R.id.articleAuthor);
viewHolder.articlePreviewDescription = (TextView) convertView.findViewById(R.id.articleDescription);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.articlePreviewTitle.setText(articlePreviewItem.getTitle());
viewHolder.articlePreviewAuthor.setText(articlePreviewItem.getAuthor());
viewHolder.articlePreviewDescription.setText(articlePreviewItem.getDescription());
return convertView;
}
}
EDIT: I added error.printStackTrace(); in the failure method and found this in logcat:
rss.reader W/System.err﹕ retrofit.RetrofitError: java.lang.ClassCastException: libcore.reflect.ParameterizedTypeImpl cannot be cast to java.lang.Class
rss.reader W/System.err﹕ at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:378)
rss.reader W/System.err﹕ at retrofit.RestAdapter$RestHandler.access$100(RestAdapter.java:220)
rss.reader W/System.err﹕ at retrofit.RestAdapter$RestHandler$2.obtainResponse(RestAdapter.java:278)
rss.reader W/System.err﹕ at retrofit.CallbackRunnable.run(CallbackRunnable.java:42)
rss.reader W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
rss.reader W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
rss.reader W/System.err﹕ at retrofit.Platform$Android$2$1.run(Platform.java:142)
rss.reader W/System.err﹕ at java.lang.Thread.run(Thread.java:818)
rss.reader W/System.err﹕ Caused by: retrofit.converter.ConversionException: java.lang.ClassCastException: libcore.reflect.ParameterizedTypeImpl cannot be cast to java.lang.Class
rss.reader W/System.err﹕ at rss.reader.SimpleXMLConverter.fromBody(SimpleXMLConverter.java:39)
rss.reader W/System.err﹕ at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:362)
rss.reader W/System.err﹕ ... 7 more
rss.reader W/System.err﹕ Caused by: java.lang.ClassCastException: libcore.reflect.ParameterizedTypeImpl cannot be cast to java.lang.Class
rss.reader W/System.err﹕ at rss.reader.SimpleXMLConverter.fromBody(SimpleXMLConverter.java:37)
rss.reader W/System.err﹕ ... 8 more
rss.reader W/System.err﹕ retrofit.RetrofitError: java.lang.ClassCastException: libcore.reflect.ParameterizedTypeImpl cannot be cast to java.lang.Class
rss.reader W/System.err﹕ at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:378)
rss.reader W/System.err﹕ at retrofit.RestAdapter$RestHandler.access$100(RestAdapter.java:220)
rss.reader W/System.err﹕ at retrofit.RestAdapter$RestHandler$2.obtainResponse(RestAdapter.java:278)
rss.reader W/System.err﹕ at retrofit.CallbackRunnable.run(CallbackRunnable.java:42)
rss.reader W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
rss.reader W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
rss.reader W/System.err﹕ at retrofit.Platform$Android$2$1.run(Platform.java:142)
rss.reader W/System.err﹕ at java.lang.Thread.run(Thread.java:818)
rss.reader W/System.err﹕ Caused by: retrofit.converter.ConversionException: java.lang.ClassCastException: libcore.reflect.ParameterizedTypeImpl cannot be cast to java.lang.Class
rss.reader W/System.err﹕ at rss.reader.SimpleXMLConverter.fromBody(SimpleXMLConverter.java:39)
rss.reader W/System.err﹕ at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:362)
rss.reader W/System.err﹕ ... 7 more
rss.reader W/System.err﹕ Caused by: java.lang.ClassCastException: libcore.reflect.ParameterizedTypeImpl cannot be cast to java.lang.Class
rss.reader W/System.err﹕ at rss.reader.SimpleXMLConverter.fromBody(SimpleXMLConverter.java:37)
rss.reader W/System.err﹕ ... 8 more
Jake Wharton's answer eventually led me to final solution as shown below. The source of the problem indeed lied within the type which was called back. It was wrongly written.
Some people might find this helpful btw; Convert XML or JSON to Java Pojo Classes - Online.
By default Simple treats elements as required fields and is strict when it comes to definition of root element. This is mentioned in the tutorial on the official site.
RSS.java
@Root(name = "rss", strict = false)
public class RSS {
@Element
private Channel channel;
@Attribute
private String version;
public Channel getChannel() {
return channel;
}
}
Channel.java
@Root(name = "channel", strict = false)
public class Channel {
@ElementList(name = "item", inline = true)
List<Article> articleList;
@Element
private String title;
@Element
private String link;
@Element
private String description;
Article.java
@Root(name = "item", strict = false)
public class Article {
@Element
private String title;
@Element
private String description;
@Element
private String link;
@Element(required = false)
private String author;
@Element(required = false)
private String pubDate;