user2893128
user2893128

Reputation: 183

Thread issue with using Jsoup on Android

I have the following code, in which I try to connect to google.com and parse the text on that site:

package com.example.parsetest;

import java.io.IOException;

import org.jsoup.*;
import org.jsoup.nodes.Document;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;

public class MainActivity extends Activity {

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

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }


    Thread downloadThread = new Thread() {                     
        public void run() {                                    
            Document doc;                                      
            try {                                              
                doc = Jsoup.connect("http://google.com/").get();
                String title = doc.title();  

                TextView console = (TextView) findViewById(R.id.textview1);
                console.setText(title);

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


}

My issue is that I'm unsure as to whether I've created my new thread properly, and where I'm supposed to call downloadThread.start() from - am I supposed to create a new class? Or do I call it from my onCreate method?

Upvotes: 0

Views: 2030

Answers (3)

Raghunandan
Raghunandan

Reputation: 133560

Yes you need to call downloadThread.start(). You cannot update ui from a background thread. Use runOnUiThread

public class MainActivity extends Activity {
    TextView console;
    String title; 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        console = (TextView) findViewById(R.id.textView1); 
        new Thread() {                     
        public void run() {                                    
            Document doc;                                      
            try {                                              
                doc = Jsoup.connect("http://google.com/").get();
                title = doc.title();  
                runOnUiThread( new Runnable()
                {
                    public void run()
                    {
                          console.setText(title); // set text on the ui thread
                    }
                });

            } catch (IOException e) {                          
                e.printStackTrace();                           
            }                                                  
        }                                                      
    }.start(); 

    }
}

As other have suggested using asynctask is easier.

http://developer.android.com/reference/android/os/AsyncTask.html

Using AsyncTask

public class MainActivity extends Activity {
    TextView console;
    String title; 
    ProgressDialog pd;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        pd = new ProgressDialog(this);
        pd.setMessage("Jsoup parsing...");
        console = (TextView) findViewById(R.id.textView1); 
        new TheTask().execute();

    }

    class TheTask extends AsyncTask<Void,String,String>
    {

        @Override
        protected String doInBackground(Void... arg0) {
            // TODO Auto-generated method stub
               Document doc;                                      
                try {                                              
                    doc = Jsoup.connect("http://google.com/").get();
                    title = doc.title();  
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
            return title;
        }

        @Override
        protected void onPostExecute(String result) {
            // TODO Auto-generated method stub
            super.onPostExecute(result);
            pd.dismiss();
            console.setText(title);
        }

        @Override
        protected void onPreExecute() {
            // TODO Auto-generated method stub
            super.onPreExecute();
            pd.show();
        }

    }
}

Upvotes: 2

ρяσѕρєя K
ρяσѕρєя K

Reputation: 132982

I'm unsure as to whether I've created my new thread properly

Yes you have created Thread in right way but inside run method you are updating TextView text which is not valid because only main thread updated ui elements instead of any other thread. you should use runOnUiThread for updating TextView :

MainActivity.this.runOnUiThread(new Runnable() {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        TextView console = (TextView) findViewById(R.id.textview1);
        console.setText(title);
    }
});

suggested way is use AsyncTask

where I'm supposed to call downloadThread.start() from

you should call downloadThread.start() in onCreate of Activity after setContentView

Upvotes: 0

Guy Gavriely
Guy Gavriely

Reputation: 11396

check out android AsyncTask usage example

AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.

the download should be taken place at doInBackground

Upvotes: 0

Related Questions