java - 尝试使用 AsyncTask 读取 RSS 时更新 UI,但不起作用

标签 java android android-asynctask rss rss-reader

我的应用程序正在读取 RSS 到 ArrayListrssItems我想做的是调用 setDataSetChanged每当将新项目添加到ArrayList时适配器的方法。我还使用 AsyncTask 从不同的线程读取 RSS。

为此,我通过了 AsyncTask进入RssParseHandler作为参数,因此处理程序可以调用 publishProgress AsyncTask的方法每当它完成读取 RSS 项目时都会返回对象。自 publishProgress是一个 protected 方法,我写了一个公共(public)包装方法,名为 publicPublishProgress因此处理程序可以在 AsyncTask 之外调用它目的。以下是我的一些代码:

public class MainActivity extends Activity {

private MainActivity local;
private List<RssItem> rssItems;
RssItemAdapter<RssItem> adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    this.rssItems = new ArrayList<RssItem>();

    this.adapter = new RssItemAdapter<RssItem>(local,
            R.layout.rss_row_view, rssItems);

    // Get references to the Fragments
    FragmentManager fm = getFragmentManager();
    // find the fragment
    newsFragment newsFragment = (newsFragment) fm
            .findFragmentById(R.id.newsFragment);

    newsFragment.setListItems(rssItems);

    newsFragment.setListAdapter(adapter);


    GetRSSDataTask task = new GetRSSDataTask(this.rssItems, this.adapter, "blah.jpg");
    task.execute("http://somesite.net/category/news/feed/");

    Log.d("RssReader", Thread.currentThread().getName());
}

这是从 AsyncTask 扩展的 GetRSSDataTask:

public class GetRSSDataTask extends AsyncTask<String, Void, Void> {

private String icon;
private RssReader rssReader;
private RssItemAdapter<RssItem> adapter;
private List<RssItem> rssItems;

public GetRSSDataTask(List<RssItem> rssItems, RssItemAdapter<RssItem> adapter, String icon) {
    super();
    this.icon = icon;
    this.adapter = adapter;
    this.rssItems = rssItems;
}

@Override
protected void onPreExecute() {

}

@Override
protected Void doInBackground(String... urls) {



    // Create a list adapter
    this.rssReader = new RssReader(urls[0], this.icon,
            this.rssItems, this);
    // Debug the task thread name
    Log.d("RssReader", Thread.currentThread().getName());

    try {

        // Parse RSS, get items
        rssReader.getItems();

    } catch (Exception e) {
        Log.e("RssReader", e.getMessage());
    }
    return null;
}

    // I created this method for the rss handler to access the publishProgress method.
public void publicPublishProgress(){
    publishProgress();
}

@Override
protected void onProgressUpdate(Void... values) {
            // update the UI
    this.adapter.notifyDataSetChanged();

}
@Override
protected void onPostExecute(Void result) {

}
}

这是 RssReader 类:

public class RssReader {

private String rssUrl;
private String icon;
private List<RssItem> rssItems;
private GetRSSDataTask task;


public RssReader(String rssUrl, String icon, List<RssItem> rssItems, GetRSSDataTask task) {
    this.rssUrl = rssUrl;
    this.icon = icon;
    this.task = task;
}


public List<RssItem> getItems() throws Exception {
    SAXParserFactory factory = SAXParserFactory.newInstance();

    SAXParser saxParser = factory.newSAXParser();
    RssParseHandler handler = new RssParseHandler(this.icon, this.rssItems, this.task);
    saxParser.parse(rssUrl, handler);
    return handler.getItems();


}

}

以及 RssParseHandler 类:

public class RssParseHandler extends DefaultHandler {

private List<RssItem> rssItems;
// We have a local reference to an object which is constructed while parser is working on an item tag
// Used to reference item while parsing
private RssItem currentItem;
// We have two indicators which are used to differentiate whether a tag title or link is being processed by the parser
// Parsing title indicator
private boolean parsingTitle;
// Parsing link indicator
private boolean parsingLink;
private String icon;
private GetRSSDataTask task;

public RssParseHandler(String icon, List<RssItem> rssItems, GetRSSDataTask task) {
    this.rssItems = rssItems;
    this.task = task;
    this.icon = icon;
}

// We have an access method which returns a list of items that are read from the RSS feed. This method will be called when parsing is done.
public List<RssItem> getItems() {
    return rssItems;
}

@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
    if ("item".equals(qName)) {
        currentItem = new RssItem();
    } else if ("title".equals(qName)) {
        parsingTitle = true;
    } else if ("link".equals(qName)) {
        parsingLink = true;
    }
}

// The EndElement method adds the  current RssItem to the list when a closing item tag is processed. It sets appropriate indicators to false -  when title and link closing tags are processed
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
    if ("item".equals(qName)) {
        currentItem.setIcon(this.icon);
        rssItems.add(currentItem);

        // update the progress
        this.task.publicPublishProgress();
        currentItem = null;
    } else if ("title".equals(qName)) {
        parsingTitle = false;
    } else if ("link".equals(qName)) {
        parsingLink = false;
    }
}

@Override
public void characters(char[] ch, int start, int length) throws SAXException {
    if (parsingTitle) {
        if (currentItem != null)
            currentItem.setTitle(new String(ch, start, length));
    } else if (parsingLink) {
        if (currentItem != null) {
            currentItem.setLink(new String(ch, start, length));
            parsingLink = false;
        }
    }
}

}

以下是错误消息:

03-08 00:46:08.420: E/AndroidRuntime(1466): FATAL EXCEPTION: AsyncTask #1
03-08 00:46:08.420: E/AndroidRuntime(1466): Process: com.example.bucknellian, PID: 1466
03-08 00:46:08.420: E/AndroidRuntime(1466): java.lang.RuntimeException: An error occured while executing doInBackground()
03-08 00:46:08.420: E/AndroidRuntime(1466):     at android.os.AsyncTask$3.done(AsyncTask.java:300)
03-08 00:46:08.420: E/AndroidRuntime(1466):     at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
03-08 00:46:08.420: E/AndroidRuntime(1466):     at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
03-08 00:46:08.420: E/AndroidRuntime(1466):     at java.util.concurrent.FutureTask.run(FutureTask.java:242)
03-08 00:46:08.420: E/AndroidRuntime(1466):     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
03-08 00:46:08.420: E/AndroidRuntime(1466):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
03-08 00:46:08.420: E/AndroidRuntime(1466):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
03-08 00:46:08.420: E/AndroidRuntime(1466):     at java.lang.Thread.run(Thread.java:841)
03-08 00:46:08.420: E/AndroidRuntime(1466): Caused by: java.lang.NullPointerException: println needs a message
03-08 00:46:08.420: E/AndroidRuntime(1466):     at android.util.Log.println_native(Native Method)
03-08 00:46:08.420: E/AndroidRuntime(1466):     at android.util.Log.e(Log.java:232)
03-08 00:46:08.420: E/AndroidRuntime(1466):     at com.example.bucknellian.util.GetRSSDataTask.doInBackground(GetRSSDataTask.java:49)
03-08 00:46:08.420: E/AndroidRuntime(1466):     at com.example.bucknellian.util.GetRSSDataTask.doInBackground(GetRSSDataTask.java:1)
03-08 00:46:08.420: E/AndroidRuntime(1466):     at android.os.AsyncTask$2.call(AsyncTask.java:288)
03-08 00:46:08.420: E/AndroidRuntime(1466):     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
03-08 00:46:08.420: E/AndroidRuntime(1466):     ... 4 more
03-08 00:46:11.590: I/Process(1466): Sending signal. PID: 1466 SIG: 9

感谢任何帮助!!

将 e.getMessage() 更改为 e.toString() 后:

03-08 01:42:24.240: W/dalvikvm(826): threadid=11: thread exiting with uncaught exception (group=0xb3a32ba8)
03-08 01:42:24.300: E/AndroidRuntime(826): FATAL EXCEPTION: AsyncTask #1
03-08 01:42:24.300: E/AndroidRuntime(826): Process: com.example.bucknellian, PID: 826
03-08 01:42:24.300: E/AndroidRuntime(826): java.lang.RuntimeException: An error occured while executing doInBackground()
03-08 01:42:24.300: E/AndroidRuntime(826):  at android.os.AsyncTask$3.done(AsyncTask.java:300)
03-08 01:42:24.300: E/AndroidRuntime(826):  at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
03-08 01:42:24.300: E/AndroidRuntime(826):  at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
03-08 01:42:24.300: E/AndroidRuntime(826):  at java.util.concurrent.FutureTask.run(FutureTask.java:242)
03-08 01:42:24.300: E/AndroidRuntime(826):  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
03-08 01:42:24.300: E/AndroidRuntime(826):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
03-08 01:42:24.300: E/AndroidRuntime(826):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
03-08 01:42:24.300: E/AndroidRuntime(826):  at java.lang.Thread.run(Thread.java:841)
03-08 01:42:24.300: E/AndroidRuntime(826): Caused by: java.lang.NullPointerException: println needs a message
03-08 01:42:24.300: E/AndroidRuntime(826):  at android.util.Log.println_native(Native Method)
03-08 01:42:24.300: E/AndroidRuntime(826):  at android.util.Log.e(Log.java:232)
03-08 01:42:24.300: E/AndroidRuntime(826):  at com.example.bucknellian.util.GetRSSDataTask.doInBackground(GetRSSDataTask.java:47)
03-08 01:42:24.300: E/AndroidRuntime(826):  at com.example.bucknellian.util.GetRSSDataTask.doInBackground(GetRSSDataTask.java:1)
03-08 01:42:24.300: E/AndroidRuntime(826):  at android.os.AsyncTask$2.call(AsyncTask.java:288)
03-08 01:42:24.300: E/AndroidRuntime(826):  at java.util.concurrent.FutureTask.run(FutureTask.java:237)
03-08 01:42:24.300: E/AndroidRuntime(826):  ... 4 more
03-08 01:42:36.100: D/dalvikvm(947): GC_FOR_ALLOC freed 70K, 5% free 3064K/3212K, paused 31ms, total 34ms
03-08 01:42:36.120: I/dalvikvm-heap(947): Grow heap (frag case) to 3.670MB for 635812-byte allocation
03-08 01:42:36.150: D/dalvikvm(947): GC_FOR_ALLOC freed 4K, 5% free 3680K/3836K, paused 28ms, total 28ms
03-08 01:42:36.230: D/RssReader(947): main
03-08 01:42:36.410: I/Choreographer(947): Skipped 32 frames!  The application may be doing too much work on its main thread.
03-08 01:42:36.470: D/gralloc_goldfish(947): Emulator without GPU emulation detected.
03-08 01:42:36.490: D/RssReader(947): AsyncTask #1
03-08 01:42:37.470: I/Choreographer(947): Skipped 36 frames!  The application may be doing too much work on its main thread.
03-08 01:42:40.100: E/RssReader(947): java.lang.NullPointerException

更改为 e.printStackTrace() 后:

03-08 01:52:31.850: W/System.err(1201): java.lang.NullPointerException
03-08 01:52:31.850: W/System.err(1201):     at com.example.bucknellian.util.RssParseHandler.endElement(RssParseHandler.java:51)
03-08 01:52:31.850: W/System.err(1201):     at org.apache.harmony.xml.ExpatParser.endElement(ExpatParser.java:156)
03-08 01:52:31.860: W/System.err(1201):     at org.apache.harmony.xml.ExpatParser.appendBytes(Native Method)
03-08 01:52:31.860: W/System.err(1201):     at org.apache.harmony.xml.ExpatParser.parseFragment(ExpatParser.java:513)
03-08 01:52:31.860: W/System.err(1201):     at org.apache.harmony.xml.ExpatParser.parseDocument(ExpatParser.java:474)
03-08 01:52:31.860: W/System.err(1201):     at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:316)
03-08 01:52:31.860: W/System.err(1201):     at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:294)
03-08 01:52:31.860: W/System.err(1201):     at javax.xml.parsers.SAXParser.parse(SAXParser.java:390)
03-08 01:52:31.860: W/System.err(1201):     at javax.xml.parsers.SAXParser.parse(SAXParser.java:266)
03-08 01:52:31.860: W/System.err(1201):     at com.example.bucknellian.util.RssReader.getItems(RssReader.java:30)
03-08 01:52:31.860: W/System.err(1201):     at com.example.bucknellian.util.GetRSSDataTask.doInBackground(GetRSSDataTask.java:44)
03-08 01:52:31.860: W/System.err(1201):     at com.example.bucknellian.util.GetRSSDataTask.doInBackground(GetRSSDataTask.java:1)
03-08 01:52:31.860: W/System.err(1201):     at android.os.AsyncTask$2.call(AsyncTask.java:288)
03-08 01:52:31.860: W/System.err(1201):     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
03-08 01:52:31.860: W/System.err(1201):     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
03-08 01:52:31.860: W/System.err(1201):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
03-08 01:52:31.860: W/System.err(1201):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
03-08 01:52:31.860: W/System.err(1201):     at java.lang.Thread.run(Thread.java:841)

将 rssItems 添加到 RssReader 后:

03-08 20:41:07.210: E/AndroidRuntime(1054): FATAL EXCEPTION: main
03-08 20:41:07.210: E/AndroidRuntime(1054): Process: com.example.bucknellian, PID: 1054
03-08 20:41:07.210: E/AndroidRuntime(1054): java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. Make sure your adapter calls notifyDataSetChanged() when its content changes. [in ListView(16908298, class android.widget.ListView) with Adapter(class com.example.bucknellian.util.RssItemAdapter)]
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.widget.ListView.layoutChildren(ListView.java:1555)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.widget.AbsListView.onLayout(AbsListView.java:2091)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.View.layout(View.java:14817)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.ViewGroup.layout(ViewGroup.java:4631)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.View.layout(View.java:14817)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.ViewGroup.layout(ViewGroup.java:4631)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.View.layout(View.java:14817)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.ViewGroup.layout(ViewGroup.java:4631)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.View.layout(View.java:14817)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.ViewGroup.layout(ViewGroup.java:4631)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.View.layout(View.java:14817)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.ViewGroup.layout(ViewGroup.java:4631)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.View.layout(View.java:14817)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.ViewGroup.layout(ViewGroup.java:4631)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at com.android.internal.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:374)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.View.layout(View.java:14817)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.ViewGroup.layout(ViewGroup.java:4631)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.View.layout(View.java:14817)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.ViewGroup.layout(ViewGroup.java:4631)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1987)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1744)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5670)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.Choreographer.doCallbacks(Choreographer.java:574)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.Choreographer.doFrame(Choreographer.java:544)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.os.Handler.handleCallback(Handler.java:733)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.os.Handler.dispatchMessage(Handler.java:95)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.os.Looper.loop(Looper.java:136)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at android.app.ActivityThread.main(ActivityThread.java:5017)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at java.lang.reflect.Method.invokeNative(Native Method)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at java.lang.reflect.Method.invoke(Method.java:515)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
03-08 20:41:07.210: E/AndroidRuntime(1054):     at dalvik.system.NativeStart.main(Native Method)

我知道这是因为我尝试在与 UI 线程不同的线程中更改 UI。你知道如何改变它吗?

最佳答案

试试这个..

使用.printStackTrace();查看错误消息

try {

    // Parse RSS, get items
    rssReader.getItems();

} catch (Exception e) {
    e.printStackTrace();
}

编辑:

RssReader.class 中添加 this.rssItems = rssItems;

public RssReader(String rssUrl, String icon, List<RssItem> rssItems, GetRSSDataTask task) {
    this.rssUrl = rssUrl;
    this.icon = icon;
    this.task = task;
    this.rssItems = rssItems;
}

关于java - 尝试使用 AsyncTask 读取 RSS 时更新 UI,但不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22265881/

相关文章:

java - Android与Json获取数据

java - 处理资源 xml 文件

android - Android 2.3.3 上带有授权 header 和 CORS 的 Ajax GET 请求

android - 在没有第三方库的情况下将图像从网络加载到网格

java - RecyclerView使用AsyncTask分页制作重复页面?

java - 在 Apache CXF REST 服务中将 JSON 数据作为请求正文提交

java - while 循环中的条件

java - Android Espresso - 测试 ListView 行

android - AsyncTask 未在从 Notification 启动的 Activity 中运行 onPostExexute

android - AsyncTask 类中的 getApplicationContext?