1

I'm getting an error stating: The constructor MainActivity.MyTask(TextView) is undefined after following a suggestion from another SO user as to how to fix my Android based web scraper:

How To Extract Table Data Via Android

I've attempted to create a constructor:

public MyTask(TextView tv) {
    // TODO Auto-generated constructor stub
}

however that does not seem to resolve the issue (the error goes away - but the textview is never updated.)

ERROR:

The constructor MainActivity.MyTask(TextView) is undefined 

SOURCE:

public class MainActivity extends Activity {

    TextView tv;
    final String URL = "http://news.google.com";

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

        tv = (TextView) findViewById(R.id.TextView01);
        new MyTask(tv).execute(URL);
    }

    private class MyTask extends AsyncTask<String, Void, String> {
        ProgressDialog prog;
        String title = "";

        @Override
        protected void onPreExecute() {
            prog = new ProgressDialog(MainActivity.this);
            prog.setMessage("Loading....");
            prog.show();
        }

        @Override
        protected String doInBackground(String... params) {
            try {
                Document doc = Jsoup.connect(params[0]).get();
                Element tableHeader = doc.select("tr").first();

                for (Element element : tableHeader.children()) {
                    // Here you can do something with each element
                    System.out.println(element.text());
                    tv.setText(element.text());
                }

                title = doc.title();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return title;
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            prog.dismiss();
            tv.setText(result);
        }
    }
}

EDIT IN RESPONSE TO Raghunandan's ANSWER:

public class MainActivity extends Activity {
    Context context;

    TextView tv;
    final String URL = "http://news.google.com";

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

        tv = (TextView) findViewById(R.id.TextView01);
        new MyTask().execute(URL);
    }

    private class MyTask extends AsyncTask<String, Void, String> {
        ProgressDialog prog;
        String title = "";

        @Override
        protected void onPreExecute() {
            prog = new ProgressDialog(MainActivity.this);
            prog.setMessage("Loading....");
            prog.show();
        }

        @Override
        protected String doInBackground(String... params) {
            try {
                Document doc = Jsoup.connect(params[0]).get();
                Element tableHeader = doc.select("tr").first();

                for (Element element : tableHeader.children()) {
                    // Here you can do something with each element
                    // System.out.println(element.text());
                    // tv.setText(element.text());
                    // //cannot update ui here.
                    // use Log.i instead of System.out.println
                }

                title = doc.title();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return value;
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            prog.dismiss();
            // tv.setText(result);
            Document doc = Jsoup.connect(params[0]).get();
            Element tableHeader = doc.select("tr").first();

            for (Element element : tableHeader.children()) {
                // Here you can do something with each element
                System.out.println(element.text());
                tv.setText(element.text());
                // cannot update ui here.

            }
        }
    }
}
Community
  • 1
  • 1
OhNoItsAnOverflow
  • 237
  • 2
  • 5
  • 13

1 Answers1

0

You have this

  new MyTask(tv).execute(URL);

But in your asycntask you does not have constructor like

  public MyTask(TextView tv)
  {

  }

There is not need to pass textview to the constructor if your asynctask is an inner class of your activity class coz you have textview declared as a activity class member.

You can set the text in onPostExecute. But you are setting text in doInbackground.

doInbackground is invoked on a background thread. So you cannot set text there. You need to update ui on the ui thread.

If asynctask is not an inner class then use a interface

Can't post response from AsyncTask to MainActivity

    public class MainActivity extends Activity {
        Context context;

            TextView tv;
            final String URL = "http://news.google.com";

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

                tv = (TextView) findViewById(R.id.textView1);
                new MyTask().execute(URL);
            }

            private class MyTask extends AsyncTask<String, Void, String> {
                ProgressDialog prog;
                String title = "";

                @Override
                protected void onPreExecute() {
                    prog = new ProgressDialog(MainActivity.this);
                    prog.setMessage("Loading....");
                    prog.show();
                }

                @Override
                protected String doInBackground(String... params) {
                    try {
                        Document doc = Jsoup.connect(params[0]).get();
                        Element tableHeader = doc.select("tr").first();

                        for (Element element : tableHeader.children()) {
                            // Here you can do something with each element
                            //System.out.println(element.text());
                            //tv.setText(element.text());
                            //cannot update ui here. 
                            // use Log.i instead of System.out.println
                        }

                        title = doc.title();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return title;
                }

                @Override
                protected void onPostExecute(String result) {
                    super.onPostExecute(result);
                    prog.dismiss();
                    tv.setText(result);
                }
            }
        }

For more info on asynctask

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

Edit:

public class MainActivity extends Activity {
    Context context;
    ArrayList<String> aa = new ArrayList<String>();
        ListView lv;
        final String URL = "http://news.google.com";

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            lv= (ListView) findViewById(R.id.listView1);
            new MyTask().execute(URL);
        }

        private class MyTask extends AsyncTask<String, Void, String> {
            ProgressDialog prog;
            String title = "";

            @Override
            protected void onPreExecute() {
                prog = new ProgressDialog(MainActivity.this);
                prog.setMessage("Loading....");
                prog.show();
            }

            @Override
            protected String doInBackground(String... params) {
                try {
                    Document doc = Jsoup.connect(params[0]).get();
                    Element tableHeader = doc.select("tr").first();

                    for (Element element : tableHeader.children()) {
                        aa.add(element.text().toString());
                    }

                    title = doc.title();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return title;
            }

            @Override
            protected void onPostExecute(String result) {
                super.onPostExecute(result);
                prog.dismiss();
                ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this,android.R.layout.simple_list_item_1,aa);
                lv.setAdapter(adapter);
            }
        }
    }

activtiy_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <ListView
        android:id="@+id/listView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" >

    </ListView>

</RelativeLayout>

Snap shot

enter image description here

Community
  • 1
  • 1
Raghunandan
  • 132,755
  • 26
  • 225
  • 256
  • Is `onPostExecute` executed on the Thread that called `execute()`? That doesn't make sense to me, it would make the `execute()` call block. – Sotirios Delimanolis Sep 19 '13 at 17:51
  • @SotiriosDelimanolis isn't onPostExecute invoked on the ui thread? – Raghunandan Sep 19 '13 at 17:54
  • 1
    That's what I was asking you lol. But yes, you are [correct](http://developer.android.com/reference/android/os/AsyncTask.html#onPostExecute(Result)) – Sotirios Delimanolis Sep 19 '13 at 17:55
  • http://developer.android.com/reference/android/os/AsyncTask.html. check the docs the topic under The 4 Steps – Raghunandan Sep 19 '13 at 17:56
  • Thank you! That resolved the compiler errors I was having... any idea why the textview still won't update with the tablerow data? – OhNoItsAnOverflow Sep 19 '13 at 18:15
  • @OhNoItsAnOverflow textview will update if you update it in `onPostExecute`. return value in `doInbackGround`. The result of background computation is param to `onPostExecute`. So you can update textview in `onPostExecute`. In the above example you can see the title only. – Raghunandan Sep 19 '13 at 18:17
  • @OhNoItsAnOverflow also it will be better you use listview instead of textview. – Raghunandan Sep 19 '13 at 18:20
  • Ok - I'll give that a shot in just a sec after I get this first issue ironed out : ) – OhNoItsAnOverflow Sep 19 '13 at 18:22
  • @OhNoItsAnOverflow no not right you have this in onPostExecute `Document doc = Jsoup.connect(params[0]).get()` all network related operation should be done on the background thread – Raghunandan Sep 19 '13 at 18:24
  • @OhNoItsAnOverflow see the edit now that should clear all your doubt. i have even posted a screen shot. If it helps do mark the answer as accepted – Raghunandan Sep 19 '13 at 18:32
  • PS - I have another somewhat simple issue I'm stuck on if you'd like to take a shot at the correct answer :) http://stackoverflow.com/questions/18904302/parsing-tablerow-data-from-correct-html-tags-via-jsoup-android – OhNoItsAnOverflow Sep 19 '13 at 20:46