开发者

How to set up a Thread and Handler for a SAX parser?

I've been trying to set up a UI Thread and Handler for a SAX parser. This is my parser without a UI Thread and Handler implemented:

public class AndroidXMLReader extends ListActivity {

    private XMLFeed myXMLFeed = null;


    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
            try {
                URL xmlUrl = new URL("http://feeds.bbci.co.uk/news/uk/rss.xml");
                SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance();
                SAXParser mySAXParser = mySAXParserFactory.newSAXParser();
                XMLReader myXMLReader = mySAXParser.getXMLReader();
                XMLHandler myXMLHandler = new XMLHandler();
                myXMLReader.setContentHandler(myXMLHandler);
                InputSource myInputSource = new InputSource(xmlUrl.openStream());
                myXMLReader.parse(myInputSource);

                myXMLFeed = myXMLHandler.getFeed();

            }

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

        if (myXMLFeed!=null)
        {
            ArrayAdapter<XMLItem> adapter =
             new ArrayAdapter<XMLItem>(this,
               android.R.layout.simple_list_item_1,myXMLFeed.getList());
            setListAdapter(adapter);
        }
        }
    }

Then here I went and tried to add the UI Thread & Handler. Edit 1 - this is the amended code as per HellBoy's reply:

   public class AndroidXMLReader extends ListActivity {

    private static final int THREAD_FINISHED = 0;
    private XMLFeed myXMLFeed = null;
    private ProgressDialog progressDialog;
    private Button refreshFeed;
    Handler handler = new Handler();

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        initControls();
    }

    public void initControls(){


          refreshFeed = (Button) findViewById(R.id.refresh);

          refreshFeed.开发者_如何学PythonsetOnClickListener(new Button.OnClickListener(){
              @Override
              public void onClick(View v){
                  progressDialog = ProgressDialog.show(AndroidXMLReader.this, "",
                            "Please wait for few seconds...", true);
                  processThread();          
              }
          });
    }
    protected void processThread() {
        Thread t = new Thread()
        {
            public void run(){
                 getNews();
                 //UI();
                 // Sends message to the handler so it updates the UI
                 handler.sendMessage(Message.obtain(mHandler, THREAD_FINISHED));

                 ; }
        };
        t.start();
    }

    private Handler mHandler = new Handler() {
        @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);

                switch (msg.what) {
                case THREAD_FINISHED:

                           progressDialog.dismiss();
                           break;    
                    };

            };
    };

    private void getNews(){
        try {
            URL xmlUrl = new URL("http://feeds.bbci.co.uk/news/uk/rss.xml");
            SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance();
            SAXParser mySAXParser = mySAXParserFactory.newSAXParser();
            XMLReader myXMLReader = mySAXParser.getXMLReader();
            XMLHandler myXMLHandler = new XMLHandler();
            myXMLReader.setContentHandler(myXMLHandler);
            InputSource myInputSource = new InputSource(xmlUrl.openStream());
            myXMLReader.parse(myInputSource);

            myXMLFeed = myXMLHandler.getFeed();

        }

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

        if (myXMLFeed!=null){
            ArrayAdapter<XMLItem> adapter =
                 new ArrayAdapter<XMLItem>(this,
                   android.R.layout.simple_list_item_1,myXMLFeed.getList());
                setListAdapter(adapter);
        }

    }
}

At the moment it hangs at the progress dialog and I can't figure out why ... Any help would be appreciated.

Edit 1 - The error message that I get now is:

Only the original thread that created a view hierarchy can touch its views.

    10-04 21:39:27.570: ERROR/AndroidRuntime(17454):     at com.android.testfeed3.AndroidXMLReader.getNews(AndroidXMLReader.java:121)
10-04 21:39:27.570: ERROR/AndroidRuntime(17454):     at com.android.testfeed3.AndroidXMLReader.access$2(AndroidXMLReader.java:85)
10-04 21:39:27.570: ERROR/AndroidRuntime(17454):     at com.android.testfeed3.AndroidXMLReader$3.run(AndroidXMLReader.java:60)
10-04 21:39:27.645: WARN/ActivityManager(2703):   Force finishing activity com.android.testfeed3/.AndroidXMLReader
10-04 21:39:33.495: ERROR/WindowManager(17454): Activity com.android.testfeed3.AndroidXMLReader has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@40527a20 that was originally added here
10-04 21:39:33.495: ERROR/WindowManager(17454): android.view.WindowLeaked: Activity com.android.testfeed3.AndroidXMLReader has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@40527a20 that was originally added here
10-04 21:39:33.495: ERROR/WindowManager(17454):     at com.android.testfeed3.AndroidXMLReader$2.onClick(AndroidXMLReader.java:50)

Any help would be appreciated.


In order to make changes to the UI the commands must come from thread that created it, i.e. the main (or UI) thread.

At a quick glance, this line:

if (myXMLFeed!=null)
{
   ArrayAdapter<XMLItem> adapter =
    new ArrayAdapter<XMLItem>(this,
      android.R.layout.simple_list_item_1,myXMLFeed.getList());
   setListAdapter(adapter);
}

needs to be put in a separate Handler and that Handler called from your new thread.


Try to put your processThread() method like this

protected void processThread() {
    Thread t = new Thread()
    {
        public void run() {
            theThread();}

    };
    t.start();
}


Just scan your code, but I don't see any problem with it. You may put some debug logs to see which line got stuck. But If I were you , I would have used AsynTask.

Thread and handler come in handy when you want to update the UI from background thread. AsynTask is used when you fire something that would block the UI.

In your case, I think AsynTask is better.

1) Android Doc of AsynTask

2) Use onPreExecute()(UI Thread) to fire up the pregress dialog you want

3) do the actually URL and SAX parse in doInBackground() (worker thread). This will run the code for you in a background thread so you don't have to init it.

4) onPostExecute() (UI Thread), close the dialog or do whatever you want to update the UI.


wait!! What could this be?

    protected void processThread() {
    Thread t = new Thread();{ <--- a semi-colon

You might wanna check your logic again inside the thread 't'.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜