尝试创建RSS阅读器的异常?

时间:2015-05-14 12:20:33

标签: android android-fragments android-asynctask rss

我正在尝试为我的应用创建一个RSS阅读器,问题是当我尝试显示我的片段不起作用并抛出异常而无效。

我正在尝试关注此示例:https://androidresearch.wordpress.com/2012/01/21/creating-a-simple-rss-application-in-android/

我怎么能这样做?

RSS阅读器片段

public class RSSReaderFrag extends Fragment implements AdapterView.OnItemClickListener{
    private final String TAG = getClass().getSimpleName() + "->";
    private ProgressDialog progress;

    //listas
    private List headlines;
    private List links;
    private ListView listRSS;

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

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.rss_feed, container, false);

        listRSS = (ListView)view.findViewById(R.id.listRSS);
        listRSS.setOnItemClickListener(this);


        return  view;
    }



    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        new AsyncTask<Void, Void, Void>(){
            @Override
            protected Void doInBackground(Void... params) {
                init();
                return null;
            }
        }.execute();
    }




    /** init RSS */
    private void init(){
        // Initializing instance variables
        headlines = new ArrayList();
        links = new ArrayList();

        try {
            URL url = new URL("http://feeds.pcworld.com/pcworld/latestnews");

            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            factory.setNamespaceAware(false);
            XmlPullParser xpp = factory.newPullParser();

            // We will get the XML from an input stream
            xpp.setInput(getInputStream(url), "UTF_8");

        /* We will parse the XML content looking for the "<title>" tag which appears inside the "<item>" tag.
         * However, we should take in consideration that the rss feed name also is enclosed in a "<title>" tag.
         * As we know, every feed begins with these lines: "<channel><title>Feed_Name</title>...."
         * so we should skip the "<title>" tag which is a child of "<channel>" tag,
         * and take in consideration only "<title>" tag which is a child of "<item>"
         *
         * In order to achieve this, we will make use of a boolean variable.
         */
            boolean insideItem = false;

            // Returns the type of current event: START_TAG, END_TAG, etc..
            int eventType = xpp.getEventType();
            while (eventType != XmlPullParser.END_DOCUMENT) {
                if (eventType == XmlPullParser.START_TAG) {

                    if (xpp.getName().equalsIgnoreCase("item")) {
                        insideItem = true;
                    } else if (xpp.getName().equalsIgnoreCase("title")) {
                        if (insideItem)
                            headlines.add(xpp.nextText()); //extract the headline
                    } else if (xpp.getName().equalsIgnoreCase("link")) {
                        if (insideItem)
                            links.add(xpp.nextText()); //extract the link of article
                    }
                }else if(eventType==XmlPullParser.END_TAG && xpp.getName().equalsIgnoreCase("item")){
                    insideItem=false;
                }

                eventType = xpp.next(); //move to next element
            }

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Binding data
        ArrayAdapter adapter = new ArrayAdapter(getView().getContext(), android.R.layout.simple_list_item_1, headlines);
        listRSS.setAdapter(adapter);
    }

   private InputStream getInputStream(URL url) {
        try {
            return url.openConnection().getInputStream();
        } catch (IOException e) {
            return null;
        }
    }


    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Uri uri = Uri.parse((String)links.get(position));
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        startActivity(intent);
    }
}

异常

05-14 09:09:58.086  21617-22201/br.com.williarts.radios.provincia E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
    java.lang.RuntimeException: An error occured while executing doInBackground()
            at android.os.AsyncTask$3.done(AsyncTask.java:299)
            at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
            at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
            at java.util.concurrent.FutureTask.run(FutureTask.java:239)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
            at java.lang.Thread.run(Thread.java:841)
     Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
            at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6818)
            at android.view.ViewRootImpl.focusableViewAvailable(ViewRootImpl.java:3335)
            at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:681)
            at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:681)
            at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:681)
            at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:681)
            at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:681)
            at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:681)
            at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:681)
            at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:681)
            at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:681)
            at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:681)
            at android.view.View.setFlags(View.java:9397)
            at android.view.View.setFocusableInTouchMode(View.java:6168)
            at android.widget.AdapterView.checkFocus(AdapterView.java:720)
            at android.widget.ListView.setAdapter(ListView.java:471)
            at br.com.williarts.radios.provincia.frags.NoticiasFrag.init(NoticiasFrag.java:136)
            at br.com.williarts.radios.provincia.frags.NoticiasFrag.access$000(NoticiasFrag.java:36)
            at br.com.williarts.radios.provincia.frags.NoticiasFrag$1.doInBackground(NoticiasFrag.java:70)
            at br.com.williarts.radios.provincia.frags.NoticiasFrag$1.doInBackground(NoticiasFrag.java:67)
            at android.os.AsyncTask$2.call(AsyncTask.java:287)
            at java.util.concurrent.FutureTask.run(FutureTask.java:234)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
            at java.lang.Thread.run(Thread.java:841)

2 个答案:

答案 0 :(得分:1)

您必须将此部分代码移到doInBackground()函数之外并在UI Thread中运行:

// Binding data
ArrayAdapter adapter = new ArrayAdapter(getView().getContext(), android.R.layout.simple_list_item_1, headlines);
listRSS.setAdapter(adapter);`
onPostExecute()

中的

仅移动listRSS.setAdapter(adapter);也足够了,但为清除移动Adapter creation

答案 1 :(得分:1)

如已经评论过,您无法从asynctask的doInBackground方法更新UI线程(在不同的线程中执行),快速解决方案是替换:

// Binding data
    ArrayAdapter adapter = new ArrayAdapter(getView().getContext(), android.R.layout.simple_list_item_1, headlines);
    listRSS.setAdapter(adapter);

使用:

 runOnUiThread(new Runnable() {
       @Override
       public void run() {
          listRSS.setAdapter(adapter);
       }
 });