Как настроить поток и обработчик для парсера SAX? - PullRequest
1 голос
/ 03 октября 2011

Я пытался настроить поток пользовательского интерфейса и обработчик для синтаксического анализатора SAX. Это мой парсер без встроенного обработчика потока и обработчика:

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);
        }
        }
    }

Затем я попытался добавить поток и обработчик пользовательского интерфейса. Редактировать 1 - это исправленный код согласно ответу HellBoy:

   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.setOnClickListener(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);
        }

    }
}

В данный момент он зависает в диалоге прогресса, и я не могу понять, почему ... Любая помощь будет оценена.

Редактировать 1 - Сообщение об ошибке, которое я получаю сейчас:

Только исходный поток, создавший иерархию представлений, может касаться его вид.

    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)

Любая помощь будет оценена.

Ответы [ 4 ]

1 голос
/ 05 октября 2011

Для внесения изменений в пользовательский интерфейс команды должны исходить из потока, который его создал, то есть основного (или пользовательского) потока.

На первый взгляд, эту строку:

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

необходимо поместить в отдельный обработчик, и этот обработчик вызывается из новой темы.

1 голос
/ 04 октября 2011

Попробуй поставить свой метод processThread () вот так

0 голосов
/ 03 октября 2011

ждать !!Что это может быть?

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

Возможно, вы захотите снова проверить свою логику в потоке 't'.

0 голосов
/ 03 октября 2011

Просто отсканируйте свой код, но я не вижу никаких проблем с ним. Вы можете поместить несколько журналов отладки, чтобы увидеть, какая строка застряла. Но на вашем месте я бы использовал AsynTask.

Поток и обработчик пригодятся, когда вы хотите обновить пользовательский интерфейс из фонового потока. AsynTask используется, когда вы запускаете что-то, что блокирует пользовательский интерфейс.

В вашем случае, я думаю, AsynTask лучше.

1) Док Android AsynTask

2) Используйте onPreExecute () (поток пользовательского интерфейса), чтобы запустить желаемое диалоговое окно подготовки

3) выполнить фактический анализ URL и SAX в doInBackground () (рабочий поток). Это запустит код для вас в фоновом потоке, поэтому вам не нужно его инициализировать.

4) onPostExecute () (поток пользовательского интерфейса), закройте диалоговое окно или сделайте все, что хотите, чтобы обновить пользовательский интерфейс.

...