java - 如何合并、创建标签并按升序排列更多 RSS 提要链接的提要,如 Yahoo Pipes 上的提要?

标签 java android rss feed yahoo-pipes

我需要获取更多 RSS Feed 的提要我必须聚合并按降序显示新闻的网址。

有些链接没有 xml <category> 的标签所以我需要创建一个:我必须知道提要来自哪里,以便我可以对它们进行分类。

这就是我要实现的目标:(对于 Source n 我指的是类别)

[![在此处输入图片描述][1]][1]

我曾经使用 Yahoo!Pipes进行所有这些更改。

我的尝试是创建一个 CustomListView对于每个 url,然后执行 AsyncTasks一次全部但无法正常工作 - 提要未按升序显示。

主 Activity

public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {
    private RSSFeed myRssFeed = null;
    String[] urlFeed = {"url1", "url2"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        for (int i = 0; i < urlFeed.length; i++) {
            News news = new News(i);
            news.execute();
        }
    }

    @Override
    public void onRefresh() {
        for (int i = 0; i < urlFeed.length; i++) {
            News news = new News(i);
            news.execute();
        }
    }

    private class News extends AsyncTask<Object, Void, Void> {
        protected int number;
        public News(int urlNumber) {
            number = urlNumber;
        }

        @Override
        protected Void doInBackground(Object... arg0) {

            String data = "";
            InputStream iStream;

            try{
                URL url = new URL(urlFeed[number]);

                // Creating an http connection to communicate with url
                HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

                // Connecting to url
                urlConnection.connect();

                // Reading data from url
                iStream = urlConnection.getInputStream();

                BufferedReader br = new BufferedReader(new InputStreamReader(iStream));

                StringBuilder sbf  = new StringBuilder();

                String line;
                while( ( line = br.readLine())  != null){
                    sbf.append(line);
                }

                data = sbf.toString();

                br.close();

                SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance();
                SAXParser mySAXParser = mySAXParserFactory.newSAXParser();
                XMLReader myXMLReader = mySAXParser.getXMLReader();
                RSSHandler myRSSHandler = new RSSHandler();
                myXMLReader.setContentHandler(myRSSHandler);
                InputSource myInputSource = new InputSource(url.openStream());
                myXMLReader.parse(myInputSource);

                myRssFeed = myRSSHandler.getFeed();

            } catch (ParserConfigurationException | IOException | SAXException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);

            if (myRssFeed != null) {

                NestedListView list = (NestedListView)findViewById(android.R.id.list);
                list.setVisibility(View.VISIBLE);
                CustomList adapter = new CustomList(MainActivity.this, myRssFeed.getList());
                adapter.addAll();
                list.setAdapter(adapter);

            } else
                Toast.makeText(MainActivity.this, "Error",
                    Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }
}

RSSFeed

public class RSSFeed {
    private String title = null;
    private String description = null;
    private String link = null;
    private String pubdate = null;
    private String image = null;
    private String enclosure = null;
    private String author = null;
    private List<RSSItem> itemList;

    RSSFeed(){
        itemList = new Vector<RSSItem>(0);
    }

    void addItem(RSSItem item){
        itemList.add(item);
    }
    RSSItem getItem(int location){
        return itemList.get(location);
    }
    List<RSSItem> getList(){
        return itemList;
    }

}

RSSItem

public class RSSItem {

    private String title = null;
    private String description = null;
    private String link = null;
    private String pubdate = null;
    private String image = null;
    private String enclosure = null;
    private String author = null;
}

自定义列表

public class CustomList extends ArrayAdapter<RSSItem> {

    private static Activity context = null;
    private final List<RSSItem> web;

    public CustomList(Activity context, List<RSSItem> web) {
        super(context, R.layout.new_listview, web);
        CustomList.context = context;
        this.web = web;
    }

    @SuppressLint("SetTextI18n")
    @Override
    public View getView(final int position, View view, ViewGroup parent) {
        LayoutInflater inflater = context.getLayoutInflater();
        @SuppressLint({"ViewHolder", "InflateParams"}) final View rowView = inflater.inflate(R.layout.new_listview, null, true);
        ImageView imageView = (ImageView)rowView.findViewById(R.id.image);
            Picasso.with(context).load(web.get(position).getImage()).into(imageView);

        TextView textView = (TextView)rowView.findViewById(R.id.title);
        textView.setText(Html.fromHtml(web.get(position).getTitle()));

        TextView textView1 = (TextView)rowView.findViewById(R.id.description);
        textView1.setText(web.get(position).getDescription());

        TextView textView2 = (TextView)rowView.findViewById(R.id.pubdate);
        textView2.setText(pubdate);

        return rowView;

    }

}

RSSHandler

public class RSSHandler extends DefaultHandler {

    final int state_unknown = 0;
    final int state_title = 1;
    final int state_description = 2;
    final int state_link = 3;
    final int state_pubdate = 4;
    final int state_enclosure = 6;
    final int state_image = 5;
    final int state_author = 7;
    int currentState = state_unknown;
    String url;

    RSSFeed feed;
    RSSItem item;

    boolean itemFound = false;

    RSSHandler(){
    }

    RSSFeed getFeed(){
        return feed;
    }

    @Override
    public void startDocument() throws SAXException {
        // TODO Auto-generated method stub
        feed = new RSSFeed();
        item = new RSSItem();

    }

    @Override
    public void startElement(String uri, String localName, String qName,
                         Attributes attributes) throws SAXException {

        // TODO Auto-generated method stub

        if (localName.equalsIgnoreCase("item")){
            itemFound = true;
            item = new RSSItem();
            currentState = state_unknown;
        }
        else if (localName.equals("enclosure")) {
            url = attributes.getValue("url");
            currentState = state_image;
        }
        else if (localName.equalsIgnoreCase("title")){
            currentState = state_title;
        }
        else if (localName.equalsIgnoreCase("description")){
            currentState = state_description;
        }
        else if (localName.equalsIgnoreCase("link")){
            currentState = state_link;
        }
        else if (localName.equalsIgnoreCase("pubdate")){
            currentState = state_pubdate;
        }
        else if (localName.equalsIgnoreCase("author")){
            currentState = state_author;
        }
        else{
            currentState = state_unknown;
        }

    }

    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        // TODO Auto-generated method stub
        if (localName.equalsIgnoreCase("item")){
            feed.addItem(item);
        }
    }

    @Override
    public void characters(char[] ch, int start, int length)
        throws SAXException {
        // TODO Auto-generated method stub

        String strCharacters = new String(ch,start,length);

        if (itemFound){
            // "item" tag found, it's item's parameter
            switch(currentState){
                case state_enclosure:
                    item.setEnclosure(strCharacters);
                    break;
                case state_title:
                    item.setTitle(strCharacters);
                    break;
                case state_image:
                    item.setImage(url);
                    break;
                case state_description:
                    item.setDescription(strCharacters);
                    break;
                case state_link:
                    item.setLink(strCharacters);
                    break;
                case state_pubdate:
                    item.setPubdate(strCharacters);
                    break;
                case state_author:
                    item.setAuthor(strCharacters);
                    break;
                default:
                    break;
            }
        }
        else{
            // not "item" tag found, it's feed's parameter
            switch(currentState){
                case state_enclosure:
                    feed.setEnclosure(strCharacters);
                    break;
                case state_title:
                    feed.setTitle(strCharacters);
                    break;
                case state_image:
                    feed.setImage(url);
                    break;
                case state_description:
                    feed.setDescription(strCharacters);
                    break;
                case state_link:
                    feed.setLink(strCharacters);
                    break;
                case state_pubdate:
                    feed.setPubdate(strCharacters);
                    break;
                case state_author:
                    feed.setAuthor(strCharacters);
                    break;
                default:
                    break;
            }
        }

        currentState = state_unknown;
    }

最佳答案

该解决方案需要不止一处更改。您需要做的第一件事是让每个完成的新闻任务将其数据添加到一个大列表中。然后可以对该列表进行排序,这需要一个 Comparator

您还需要一个名称列表,以显示在图像中称为 Source n 的占位符中,最后,为了比较它们,您需要将日期解析为实际日期。

public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {

    private List<RSSItem> totalRssFeed = new ArrayList<>();
    String[] urlFeed = {"MyURL", "MyUrl2", "MyUrl3"};
    String[] names = {"Name", "Name2", "Name3"} 
    private CustomList adapter;

    @Override
    public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);
        ListView list = (ListView) findViewById(android.R.id.list);
        adapter = new CustomList(MainActivity.this);
        list.setAdapter( adapter );
    }

    @Override
    protected void onResume() {
        // do this here and you dont need to repeat it in refresh and create
        for (int i = 0; i < urlFeed.length; i++) {
            News news = new News(i);
            news.execute();
        }
    }

    public class CustomList extends ArrayAdapter<RSSItem> {

        ...

        public CustomList(Activity context) { //dont start with default data
            super(context, R.layout.new_listview, null);
        }

        ...

    }

    private class News extends AsyncTask<Object, Void, Void> {

        protected int number;

        public News(int urlNumber) {
            number = urlNumber;
        }

        @Override
        protected Void doInBackground(Object... arg0) {
            try {

                //no need to do the input stuff you were doing before here?
                URL url = new URL(urlFeed[number]);
                SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance();
                SAXParser mySAXParser = mySAXParserFactory.newSAXParser();
                XMLReader myXMLReader = mySAXParser.getXMLReader();
                RSSHandler myRSSHandler = new RSSHandler(names[number]);
                myXMLReader.setContentHandler(myRSSHandler);
                InputSource myInputSource = new InputSource(url.openStream());
                myXMLReader.parse(myInputSource);
                totalRssFeed.addAll(myRSSHandler.getFeed());
                Collections.sort(totalRssFeed);

            } catch (ParserConfigurationException | IOException | SAXException e) { /* stuff */ }
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            adapter.clear();
            adapter.addAll(totalRssFeed);
        }

    }

    public class RSSItem implements Comparable<RSSItem> {

        public String tag;
        public Date pubdate; //just public so i didnt need setters in this example

        public RSSItem(String defaultTagToUse) {
            //You should set the default to whatever you want displayed
            //when the tag for <category> is missing, and just update it normally otherwise
            tag = defaultTagToUse;
        }

        void setPubDate(Date date) {
            pubdate = date;
        }

        ...

        @Override
        public int compareTo(@NonNull RSSItem another) {
            int res;
            if (pubdate == null) {
                if (another.pubdate == null) {
                    res = 0;
                } else {
                    res = -1;
                }
            } else {
                if (another.pubdate == null || pubdate.getTime() > another.pubdate.getTime()) {
                    res = 1;
                } else {
                    res = -1;
                }
            }
            return res;
        }

    }

    public class RSSHandler extends DefaultHandler {

        ...
        List<RSSItem> feed;
        RSSItem item;
        String mName;

        public RssHandler(String name) {
            mName = name;
        } 

        List<RSSItem> getFeed() {
            return feed;
        }

        @Override
        public void startDocument() throws SAXException {
            feed = new ArrayList<>();
        }

        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            if (localName.equalsIgnoreCase("item")) {
                itemFound = true;
                item = new RSSItem( name ); 
                currentState = state_unknown;
            } else ...
        }

        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            if (localName.equalsIgnoreCase("item")) {
                feed.add(item);
            }
        }

        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            ...
            case state_pubdate:
                SimpleDateFormat formatter = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z"); //make sure you match the format from your XML
                item.setPubdate( formatter.parse(stringCharacters) );
            break;
            ...
        }
    }
}

所有 ... 的意思是让一切保持原样

关于java - 如何合并、创建标签并按升序排列更多 RSS 提要链接的提要,如 Yahoo Pipes 上的提要?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35538254/

相关文章:

java - 如何实现更新服务在后台运行?

android 二维位图绘制

java.lang.UnsatisfiedLinkError : Couldn't load native_sample from loader

python - 垃圾收集 python rss 内存

reactjs - 如何从 RSS 源的内容原始数据中获取 html 元素 (gatsby-plugin-feed)

php - mysql 数据库中存储 rss feed 的一些问题

java - NoClassDefFoundError : org/w3c/dom/ls/DocumentLS - issue occurring only on deployment after having fixed it on compile time

java - 如何使用静态成员泛化 Java 枚举?

java - 文本表示

java - 是否可以为 Tomcat 使用相同的代码库?