我如何在解析器上使用异步



我一直在阅读本教程,并遇到了它使用非常低的API的问题。我得到了NetworkOnMainThreadException。我在stackoverflow上找到了这个答案,说我必须使用asynctask。

我尝试在一个空的项目上使用Asynctask使用另一个工作,该教程正常工作。

我的问题是我需要更改此项目,以便可以在更高的API上使用它。因此,是AndroidSaxFeedParser是一个子类,异步是超级类,并且在AndroidSaxFeedParser上使用了错误行,它扩展了BaseFeedParser和BaseFeedParser扩展了FeedParser,扩展了FeedParser,这是一个接口(BTW,我一直认为接口已经实现了,而不是Extended?)。

更准确地说,错误在这些行上(用--->):AndroidSaxFeedParser.java:

try
{
--->    Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8, root.getContentHandler());
}
catch (Exception e)
{
--->    throw new RuntimeException(e);
}

Messagelist.java:

private void loadFeed(ParserType type)
{
    try
    {
        Log.i("AndroidNews", "ParserType=" + type.name());
        FeedParser parser = FeedParserFactory.getParser(type);
        long start = System.currentTimeMillis();

    --->    messages = parser.parse();
        long duration = System.currentTimeMillis() - start;
        Log.i("AndroidNews", "Parser duration=" + duration);
        String xml = writeXml();
        Log.i("AndroidNews", xml);
        List<String> titles = new ArrayList<String>(messages.size());
        for (Message msg : messages)
        {
            titles.add(msg.getTitle());
        }
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.row, titles);
        this.setListAdapter(adapter);
    }
    catch (Throwable t)
    {
        Log.e("AndroidNews", t.getMessage(), t);
    }
}

basefeedparser.java:

protected InputStream getInputStream()
{
    try
    {
    --->    return feedUrl.openConnection().getInputStream();
    }
    catch (IOException e)
    {
        throw new RuntimeException(e);
    }
}

那么,我应该在哪里以及如何使用异步。(我只使用AndroidSaxparser,因此可以忽略教程中的其他解析器)。

androidSaxFeedParser.java

public class AndroidSaxFeedParser extends BaseFeedParser
{
    static final String RSS = "rss";
    public AndroidSaxFeedParser(String feedUrl)
    {
        super(feedUrl);
    }
    public List<Message> parse()
    {
        final Message currentMessage = new Message();
        RootElement root = new RootElement(RSS);
        final List<Message> messages = new ArrayList<Message>();
        Element channel = root.getChild(CHANNEL);
        Element item = channel.getChild(ITEM);
        item.setEndElementListener(new EndElementListener()
        {
            public void end()
            {
                messages.add(currentMessage.copy());
            }
        });
        item.getChild(TITLE).setEndTextElementListener(new EndTextElementListener()
        {
            public void end(String body)
            {
                currentMessage.setTitle(body);
            }
        });
        item.getChild(LINK).setEndTextElementListener(new EndTextElementListener()
        {
            public void end(String body)
            {
                currentMessage.setLink(body);
            }
        });
        item.getChild(DESCRIPTION).setEndTextElementListener(new EndTextElementListener()
        {
            public void end(String body)
            {
                currentMessage.setDescription(body);
            }
        });
        item.getChild(PUB_DATE).setEndTextElementListener(new EndTextElementListener()
        {
            public void end(String body)
            {
                currentMessage.setDate(body);
            }
        });
        try
        {
            Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8, root.getContentHandler());
        }
        catch (Exception e)
        {
            throw new RuntimeException(e);
        }
        return messages;
    }
}

basefeedparser.java

public abstract class BaseFeedParser implements FeedParser
{
    // names of the XML tags
    static final String CHANNEL = "channel";
    static final String PUB_DATE = "pubDate";
    static final String DESCRIPTION = "description";
    static final String LINK = "link";
    static final String TITLE = "title";
    static final String ITEM = "item";
    private final URL feedUrl;
    protected BaseFeedParser(String feedUrl)
    {
        try
        {
            this.feedUrl = new URL(feedUrl);
        }
        catch (MalformedURLException e)
        {
            throw new RuntimeException(e);
        }
    }
    protected InputStream getInputStream()
    {
        try
        {
            return feedUrl.openConnection().getInputStream();
        }
        catch (IOException e)
        {
            throw new RuntimeException(e);
        }
    }
}

feedParser.java

public interface FeedParser
{
    List<Message> parse();
}

feedparserfactory.java

public abstract class FeedParserFactory
{
    static String feedUrl = "http://example.com/feed/";
    public static FeedParser getParser()
    {
        return getParser(ParserType.ANDROID_SAX);
    }
    public static FeedParser getParser(ParserType type)
    {
        switch (type)
        {
        case SAX:
            return new SaxFeedParser(feedUrl);
        case DOM:
            return new DomFeedParser(feedUrl);
        case ANDROID_SAX:
            return new AndroidSaxFeedParser(feedUrl);
        case XML_PULL:
            return new XmlPullFeedParser(feedUrl);
        default:
            return null;
        }
    }
}

message.java

public class Message implements Comparable<Message>
{
    static SimpleDateFormat FORMATTER = new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss Z",  Locale.ENGLISH);
    private String title;
    private URL link;
    private String description;
    private Date date;
    public String getTitle()
    {
        return title;
    }
    public void setTitle(String title)
    {
        this.title = title.trim();
    }
    // getters and setters omitted for brevity
    public URL getLink()
    {
        return link;
    }
    public void setLink(String link)
    {
        try
        {
            this.link = new URL(link);
        }
        catch (MalformedURLException e)
        {
            throw new RuntimeException(e);
        }
    }
    public String getDescription()
    {
        return description;
    }
    public void setDescription(String description)
    {
        this.description = description.trim();
    }
    public String getDate()
    {
        return FORMATTER.format(this.date);
    }
    public void setDate(String date)
    {
        // pad the date if necessary
        while (!date.endsWith("00"))
        {
            date += "0";
        }
        try
        {
            this.date = FORMATTER.parse(date.trim());
        }
        catch (ParseException e)
        {
            throw new RuntimeException(e);
        }
    }
    public Message copy()
    {
        Message copy = new Message();
        copy.title = title;
        copy.link = link;
        copy.description = description;
        copy.date = date;
        return copy;
    }
    @Override
    public String toString()
    {
        StringBuilder sb = new StringBuilder();
        sb.append("Title: ");
        sb.append(title);
        sb.append('n');
        sb.append("Date: ");
        sb.append(this.getDate());
        sb.append('n');
        sb.append("Link: ");
        sb.append(link);
        sb.append('n');
        sb.append("Description: ");
        sb.append(description);
        return sb.toString();
    }
    @Override
    public int hashCode()
    {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((date == null) ? 0 : date.hashCode());
        result = prime * result + ((description == null) ? 0 : description.hashCode());
        result = prime * result + ((link == null) ? 0 : link.hashCode());
        result = prime * result + ((title == null) ? 0 : title.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj)
    {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Message other = (Message) obj;
        if (date == null)
        {
            if (other.date != null)
                return false;
        }
        else if (!date.equals(other.date))
            return false;
        if (description == null)
        {
            if (other.description != null)
                return false;
        }
        else if (!description.equals(other.description))
            return false;
        if (link == null)
        {
            if (other.link != null)
                return false;
        }
        else if (!link.equals(other.link))
            return false;
        if (title == null)
        {
            if (other.title != null)
                return false;
        }
        else if (!title.equals(other.title))
            return false;
        return true;
    }
    public int compareTo(Message another)
    {
        if (another == null)
            return 1;
        // sort descending, most recent first
        return another.date.compareTo(date);
    }
}

Messagelist.java

public class MessageList extends ListActivity
{
    private List<Message> messages;
    @Override
    public void onCreate(Bundle icicle)
    {
        super.onCreate(icicle);
        setContentView(R.layout.main);
        loadFeed(ParserType.ANDROID_SAX);
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        super.onCreateOptionsMenu(menu);
        menu.add(Menu.NONE, ParserType.ANDROID_SAX.ordinal(), ParserType.ANDROID_SAX.ordinal(), R.string.android_sax);
        menu.add(Menu.NONE, ParserType.SAX.ordinal(), ParserType.SAX.ordinal(), R.string.sax);
        menu.add(Menu.NONE, ParserType.DOM.ordinal(), ParserType.DOM.ordinal(), R.string.dom);
        menu.add(Menu.NONE, ParserType.XML_PULL.ordinal(), ParserType.XML_PULL.ordinal(), R.string.pull);
        return true;
    }
    @SuppressWarnings("unchecked")
    @Override
    public boolean onMenuItemSelected(int featureId, MenuItem item)
    {
        super.onMenuItemSelected(featureId, item);
        ParserType type = ParserType.values()[item.getItemId()];
        ArrayAdapter<String> adapter = (ArrayAdapter<String>) this.getListAdapter();
        if (adapter.getCount() > 0)
        {
            adapter.clear();
        }
        this.loadFeed(type);
        return true;
    }
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id)
    {
        super.onListItemClick(l, v, position, id);
        Intent viewMessage = new Intent(Intent.ACTION_VIEW, Uri.parse(messages.get(position).getLink().toExternalForm()));
        this.startActivity(viewMessage);
    }
    private void loadFeed(ParserType type)
    {
        try
        {
            Log.i("AndroidNews", "ParserType=" + type.name());
            FeedParser parser = FeedParserFactory.getParser(type);
            long start = System.currentTimeMillis();
            messages = parser.parse();
            long duration = System.currentTimeMillis() - start;
            Log.i("AndroidNews", "Parser duration=" + duration);
            String xml = writeXml();
            Log.i("AndroidNews", xml);
            List<String> titles = new ArrayList<String>(messages.size());
            for (Message msg : messages)
            {
                titles.add(msg.getTitle());
            }
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.row, titles);
            this.setListAdapter(adapter);
        }
        catch (Throwable t)
        {
            Log.e("AndroidNews", t.getMessage(), t);
        }
    }
    private String writeXml()
    {
        XmlSerializer serializer = Xml.newSerializer();
        StringWriter writer = new StringWriter();
        try
        {
            serializer.setOutput(writer);
            serializer.startDocument("UTF-8", true);
            serializer.startTag("", "messages");
            serializer.attribute("", "number", String.valueOf(messages.size()));
            for (Message msg : messages)
            {
                serializer.startTag("", "message");
                serializer.attribute("", "date", msg.getDate());
                serializer.startTag("", "title");
                serializer.text(msg.getTitle());
                serializer.endTag("", "title");
                serializer.startTag("", "url");
                serializer.text(msg.getLink().toExternalForm());
                serializer.endTag("", "url");
                serializer.startTag("", "body");
                serializer.text(msg.getDescription());
                serializer.endTag("", "body");
                serializer.endTag("", "message");
            }
            serializer.endTag("", "messages");
            serializer.endDocument();
            return writer.toString();
        }
        catch (Exception e)
        {
            throw new RuntimeException(e);
        }
    }
}

parsertype.java

public enum ParserType
{
    SAX, DOM, ANDROID_SAX, XML_PULL;
}

rsshandler.java

public class RssHandler extends DefaultHandler
{
    private List<Message> messages;
    private Message currentMessage;
    private StringBuilder builder;
    public List<Message> getMessages()
    {
        return this.messages;
    }
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException
    {
        super.characters(ch, start, length);
        builder.append(ch, start, length);
    }
    @Override
    public void endElement(String uri, String localName, String name) throws SAXException
    {
        super.endElement(uri, localName, name);
        if (this.currentMessage != null)
        {
            if (localName.equalsIgnoreCase(TITLE))
            {
                currentMessage.setTitle(builder.toString());
            }
            else if (localName.equalsIgnoreCase(LINK))
            {
                currentMessage.setLink(builder.toString());
            }
            else if (localName.equalsIgnoreCase(DESCRIPTION))
            {
                currentMessage.setDescription(builder.toString());
            }
            else if (localName.equalsIgnoreCase(PUB_DATE))
            {
                currentMessage.setDate(builder.toString());
            }
            else if (localName.equalsIgnoreCase(ITEM))
            {
                messages.add(currentMessage);
            }
            builder.setLength(0);
        }
    }
    @Override
    public void startDocument() throws SAXException
    {
        super.startDocument();
        messages = new ArrayList<Message>();
        builder = new StringBuilder();
    }
    @Override
    public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException
    {
        super.startElement(uri, localName, name, attributes);
        if (localName.equalsIgnoreCase(ITEM))
        {
            this.currentMessage = new Message();
        }
    }
}
public class ParseAsync extends AsyncTask<Url, Void, ArrayList<FeedItem>> {
    @Override
    protected ArrayList<FeedItem> doInBackground(Url... params) {
        //url as parametr, long time operation
        return YourParser.parseFeed(params[0])
    }
    @Override
    protected void onPostExecute(ArrayList<FeedItem> result) {
        // this we get result of parser in ui thread
    }
}

在UI线程中

ParseAsync task = new ParseAsync();
task.execute("www.example.ru/feed.rss")

答案

我解决了我的问题,如果有人有兴趣,您可以阅读该问题。

我认为问题是因为网络threadexception,所以您要做的是您需要添加strictmode

您在哪里使用异步任务,因此只需在异步任务的预先添加此linke

int SDK_INT = android.os.Build.VERSION.SDK_INT;
if (SDK_INT>8){
StrictMode.ThreadPolicy policy = new   StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy); 
}

希望这能解决您的问题

相关内容

  • 没有找到相关文章

最新更新