简体   繁体   English

改造和简单的问题 - 尝试为Android制作RSS阅读器

[英]Issue with Retrofit and Simple - attempt at making a RSS Reader for Android

I'm trying to download XML data with Retrofit and parse it with Simple and then load it into a ListView. 我正在尝试使用Retrofit下载XML数据并使用Simple解析它,然后将其加载到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 我正在使用此处找到的转换器 - 我已将其复制到我的项目改造/转换器/ 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(); 编辑:我添加了error.printStackTrace(); in the failure method and found this in logcat: 在失败方法中,在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

This is a Retrofit bug. 这是一个改造bug。 Please file a GitHub issue on the project. 请在项目中提交GitHub问题。

As a workaround for now, don't use a generic type as the top-level type. 作为现在的解决方法,请不要使用泛型类型作为顶级类型。

public final class ArticleList extends ArrayList<Article> {
}

public interface Service {
  @GET("/rss/news")
  public void getArticle(Callback<ArticleList> callback);
}

Jake Wharton's answer eventually led me to final solution as shown below. Jake Wharton的回答最终导致我得出最终解决方案,如下所示。 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 . 将XML或JSON转换为Java Pojo类 - 在线

By default Simple treats elements as required fields and is strict when it comes to definition of root element. 默认情况下,Simple将元素视为必需字段,并且在定义根元素时是严格的。 This is mentioned in the tutorial on the official site. 这在官方网站的教程中提到。

RSS.java 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 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 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;

I think it should be pointed out clearly on the RetroFit website: Type variables are forbidded to use in response types . 我认为应该在RetroFit网站上清楚地指出: 类型变量被禁止在响应类型中使用

Source: Issue #807 on GitHub. 资料来源:GitHub上的问题#807

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM