Using Android AsyncTask to download an html file

I just started with android, and I'm working on a simple application that should download the contents of an html file. I am using AsyncTask as suggested, but I ran into one problem. In the following code (I followed the tutorial code), I get tv cannot be resolved for the onPostExecute method. How to access the downloaded file? Thank you:

 public class FlashResults extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView tv = new TextView(this); setContentView(tv); readWebpage(tv); } protected class DownloadPage extends AsyncTask<String, Void, String> { protected String doInBackground(String... urls) { String responseStr = null; try { for (String url : urls) { DefaultHttpClient httpClient = new DefaultHttpClient(); HttpGet get = new HttpGet(url); HttpResponse httpResponse = httpClient.execute(get); HttpEntity httpEntity = httpResponse.getEntity(); responseStr = EntityUtils.toString(httpEntity); } } catch (UnsupportedEncodingException e) { } catch (ClientProtocolException e) { } catch (IOException e) { } return responseStr; } protected void onPostExecute(String result) { tv.setText(result); } } public void readWebpage(View v) { DownloadPage task = new DownloadPage(); task.execute(new String[] { "http://seznam.cz" }); } 

}

+4
source share
5 answers

All other answers proposed so far will work. However, I would add a couple more notes:

  • If you are only accessing TextView tv inside this onCreate and DownloadPage function, you can restrict access to tv by providing it directly to the DownloadPage constructor
  • for something useful, like DownloadPage AsyncTask, I usually remove it from the inner class of any activity and instead put it in an open class called "Utils", which can be used by many other actions as needed. (modularity in code)
  • if you intend to use an inner class (completely legal), it is always recommended to make it private and static for what you are doing.

Something like that:

 public class FlashResults extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView tv = new TextView(this); setContentView(tv); readWebpage(tv); } public void readWebpage(View v) { DownloadPage task = new DownloadPage(tv); task.execute(new String[] { "http://seznam.cz" }); } private static class DownloadPage extends AsyncTask<String, Void, String> { private TextView textView; public DownloadPage(TextView tv){ textView = tv; } protected String doInBackground(String... urls) { String responseStr = null; try { for (String url : urls) { DefaultHttpClient httpClient = new DefaultHttpClient(); HttpGet get = new HttpGet(url); HttpResponse httpResponse = httpClient.execute(get); HttpEntity httpEntity = httpResponse.getEntity(); responseStr = EntityUtils.toString(httpEntity); } } catch (UnsupportedEncodingException e) { } catch (ClientProtocolException e) { } catch (IOException e) { } return responseStr; } protected void onPostExecute(String result) { if (textView != null) { textView.setText(result); } } } } 

}

+4
source

One approach is to do as the other answers suggest and make the instance level tv . Alternatively, you can create a TextView field in your AsyncTask and pass the link to the constructor:

 ... public void readWebpage(TextView v) { DownloadPage task = new DownloadPage(v); task.execute(new String[] { "http://seznam.cz" }); } ... protected class DownloadPage extends AsyncTask<String, Void, String> { protected String doInBackground(String... urls) { ... } TextView tv = null; public DownloadPage(TextView tv){ this.tv = tv; } ... } 
+3
source

If you want the variable to be accessible outside the method, you need to declare it outside the method. This is a basic programming concept called scope.

Change your code like this:

 public class FlashResults extends Activity { private TextView tv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); tv = new TextView(this); setContentView(tv); readWebpage(tv); } 

and it will be available for anything inside FlashResults .

+1
source

Try making a textual representation of the class level variable.

 private TextView tv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); tv = new TextView(this); setContentView(tv); readWebpage(tv); } 

Another option would be to declare the anonymity of your AsyncTask, declaring the TextView final in the same method as your task declaration. Greetings

+1
source

You must make tv a feild to make it accessible from a subclass.

  public class FlashResults extends Activity { TextView tv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); tv = new TextView(this); setContentView(tv); readWebpage(tv); } protected class DownloadPage extends AsyncTask<String, Void, String> { protected String doInBackground(String... urls) { String responseStr = null; try { for (String url : urls) { DefaultHttpClient httpClient = new DefaultHttpClient(); HttpGet get = new HttpGet(url); HttpResponse httpResponse = httpClient.execute(get); HttpEntity httpEntity = httpResponse.getEntity(); responseStr = EntityUtils.toString(httpEntity); } } catch (UnsupportedEncodingException e) { } catch (ClientProtocolException e) { } catch (IOException e) { } return responseStr; } protected void onPostExecute(String result) { tv.setText(result); } } public void readWebpage(View v) { DownloadPage task = new DownloadPage(); task.execute(new String[] { "http://seznam.cz" }); } } 
0
source

Source: https://habr.com/ru/post/1445564/


All Articles