Retrofit 和 Simple 的问题 - 尝试为 Android 制作 RSS 阅读器
Issue with Retrofit and Simple - attempt at making a RSS Reader for Android
我正在尝试使用 Retrofit 下载 XML 数据并使用 Simple 对其进行解析,然后将其加载到 ListView 中。
遗憾的是,下载的数据不会出现在屏幕上。谁能告诉我问题出在哪里?
这是我的模型:
@Root(name = "item")
public class Article {
@Element(name = "title")
private String title;
@Element(name = "author")
private String author;
@Element(name = "description")
private String description;
接口代码:
public interface Service {
@GET("/rss/news")
public void getArticle(Callback<List<Article>> callback);
}
片段代码:
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);
}
}
我正在使用此处找到的转换器 - 我已将其复制到我的项目中 retrofit/converter/SimpleXMLConverter.java
最后,适配器的代码:
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;
}
}
编辑:
我添加了 error.printStackTrace();在失败方法中并在 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.access0(RestAdapter.java:220)
rss.reader W/System.err﹕ at retrofit.RestAdapter$RestHandler.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.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.access0(RestAdapter.java:220)
rss.reader W/System.err﹕ at retrofit.RestAdapter$RestHandler.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.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
这是一个 Retrofit 错误。请提交关于项目的 GitHub 问题。
作为目前的解决方法,不要使用泛型类型作为顶级类型。
public final class ArticleList extends ArrayList<Article> {
}
public interface Service {
@GET("/rss/news")
public void getArticle(Callback<ArticleList> callback);
}
Jake Wharton 的回答最终使我找到了如下所示的最终解决方案。
问题的根源确实在于回调的类型。写错了。
有些人可能会觉得这有帮助顺便说一句; Convert XML or JSON to Java Pojo Classes - Online.
默认情况下,Simple 将元素视为必填字段,并且在定义根元素时是严格的。这个在官网的教程里有提到
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;
我觉得应该在RetroFit网站上明确指出:类型变量禁止在响应类型中使用。
来源:Issue #807 GitHub。
我正在尝试使用 Retrofit 下载 XML 数据并使用 Simple 对其进行解析,然后将其加载到 ListView 中。
遗憾的是,下载的数据不会出现在屏幕上。谁能告诉我问题出在哪里?
这是我的模型:
@Root(name = "item")
public class Article {
@Element(name = "title")
private String title;
@Element(name = "author")
private String author;
@Element(name = "description")
private String description;
接口代码:
public interface Service {
@GET("/rss/news")
public void getArticle(Callback<List<Article>> callback);
}
片段代码:
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);
}
}
我正在使用此处找到的转换器 - 我已将其复制到我的项目中 retrofit/converter/SimpleXMLConverter.java
最后,适配器的代码:
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;
}
}
编辑: 我添加了 error.printStackTrace();在失败方法中并在 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.access0(RestAdapter.java:220)
rss.reader W/System.err﹕ at retrofit.RestAdapter$RestHandler.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.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.access0(RestAdapter.java:220)
rss.reader W/System.err﹕ at retrofit.RestAdapter$RestHandler.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.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
这是一个 Retrofit 错误。请提交关于项目的 GitHub 问题。
作为目前的解决方法,不要使用泛型类型作为顶级类型。
public final class ArticleList extends ArrayList<Article> {
}
public interface Service {
@GET("/rss/news")
public void getArticle(Callback<ArticleList> callback);
}
Jake Wharton 的回答最终使我找到了如下所示的最终解决方案。 问题的根源确实在于回调的类型。写错了。
有些人可能会觉得这有帮助顺便说一句; Convert XML or JSON to Java Pojo Classes - Online.
默认情况下,Simple 将元素视为必填字段,并且在定义根元素时是严格的。这个在官网的教程里有提到
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;
我觉得应该在RetroFit网站上明确指出:类型变量禁止在响应类型中使用。
来源:Issue #807 GitHub。