0

I want change the text of a textView to match the title of a website.

For this, I'm connecting to https://www.google.com and getting its html source code. Then I fetch the title tag from it. (using JSoup)

The problem is that now I don't know how to change the textView. Since the networking is happening in a background thread, I don't have access to it. How and where should I do it?

Also, I know it connected successfully thanks to Log.w.

Here's what I have:

MainActivity

public class MainActivity extends AppCompatActivity {

    Button btnConnect;

    final String URL = "https://www.google.com";

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

        btnConnect = (Button) findViewById(R.id.btnConnect);
        btnConnect.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // launch networking task
                new EstablishConnectionTask().execute(URL);
            }
        });


    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.awakened.tirafesi.awakenedprototype.MainActivity">

    <Button
        android:text="Establish Connection"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:id="@+id/btnConnect" />

    <TextView
        android:text="Placeholder"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="87dp"
        android:id="@+id/txtTitle" />
</RelativeLayout>

EstablishConnectionTask

public class EstablishConnectionTask extends AsyncTask<String, Void, String> {


    @Override
    protected String doInBackground(String... urls) {

        String title;

        try {
            Document doc = Jsoup.connect(urls[0]).get();
            title = doc.title();

        } catch (IOException e) {
            e.printStackTrace();
            title = "NO";
        }

        return title;
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);

        Log.w("Title", s);
    }
}
Tirafesi
  • 1,297
  • 2
  • 18
  • 36
  • Write a listener and send it to your **EstablishConnectionTask** then in onPostExecute just call your interface method. In your MainActivity first implement that listener and in it's override method you can set the textView's title. – eminuluyol Feb 01 '17 at 15:45
  • 1
    To build on what @eminuluyol said, this question gives a code example: http://stackoverflow.com/questions/9447646/how-do-i-send-data-back-from-onpostexecute-in-an-asynctask – RScottCarson Feb 01 '17 at 15:47
  • I dont get it... How would the override of the interface method on MainActivity affect the call on the interface in onPostExecute? Would you mind adding the code for it please? – Tirafesi Feb 01 '17 at 16:06
  • @Tirafesi check out the answer I posted man – W4R10CK Feb 01 '17 at 16:46

3 Answers3

1

Initialize TextView inside onCreate() same as you did for Button. Pass the textView, to Asynctask using the Class Constructor:

Complete Solved Code:

public class MainActivity extends AppCompatActivity {

Button btnConnect;
TextView textView;

final String URL = "https://www.google.com";

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

    textView = (TextView) findViewById(R.id.txtTitle);
    btnConnect = (Button) findViewById(R.id.btnConnect);
    btnConnect.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {

            //pass TextView of this class to Asynctask cass
            new EstablishConnectionTask(textView).execute(URL);
        }
    });
  }
}

Asynctask Class:

public class EstablishConnectionTask extends AsyncTask<String, Void, String> {

public TextView textView;

//constructor to pass textView
public EstablishConnectionTask(TextView textView){
    this.textView = textView;
}

@Override
protected String doInBackground(String... urls) {

    String title;
    try {
        Document doc = Jsoup.connect(urls[0]).get();
        title = doc.title();

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

@Override
protected void onPostExecute(String s) {
    super.onPostExecute(s);
    textView.setText(s); // add title to textView

    Log.w("Title", s);
 }
}
W4R10CK
  • 5,502
  • 2
  • 19
  • 30
0

This question shows you how to solve your issue: how do i send data back from onPostExecute in an AsyncTask?.

Change the TextView in the doStuff() interface method on the calling activity.

Community
  • 1
  • 1
RScottCarson
  • 980
  • 5
  • 20
0

I am assuming you want know, how to access or change the UI components from the doInBackground() method or a background thread, provided AsyncTask or . To achieve this you use a handler. For example in the AsyncTask Class initialize an object of Handler now call method handler.post() in doInBackground() method or in Run() method of thread like below

Handler handler = new Handler();
handler.post(new Runnable{
 @overide
 public void run(){
  textView.setText("Changed");
 }
});

remember to initialize the handler outside the doInBackground() or run() method;