Updating a TextView in ASyncTask - android

After trawling for ages trying to find an understandable solution to my problems i gave up and came here to see if you can help.
My Objective : Update a TextView to count from 1 to 99999 every second without hanging the main thread.
package com.myapp.counter;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myBackgroundThread myThread = new myBackgroundThread();
myThread.execute();
}
private class myBackgroundThread extends AsyncTask<Void,Integer,Void>
{
int maxTimer = 99999;
int i = 0;
//Assign the textView in MainActivity to a variable myCounter.
TextView myCounter = (TextView)findViewById(R.id.idCounter);
#Override
protected void onPreExecute() {
}
#Override
protected Void doInBackground(Void... params) {
// Toast.makeText(getApplicationContext(),"InBackground",Toast.LENGTH_SHORT).show();
//Tried Toasting a message upon this starting but just threw an error
//Guess because i tried to add a UI component in a background task.
for(int i = 0; i < maxTimer; i++)
{
publishProgress(i);
}
return null;
}
//onProgressUpdate is never firing from publishProgress...
protected void onProgressUpdate(Integer i) {
Toast.makeText(getApplicationContext(),i,Toast.LENGTH_SHORT).show();
//Updatet he counter from 000 to 1,2,3,4 etc.
myCounter.setText(i);
}
protected void onPostExecute(Void result)
{
}
}
public void startTimer(View view)
{
TextView myText = (TextView)findViewById(R.id.textView);
// Toast.makeText(this,"Started...", Toast.LENGTH_SHORT).show();
}
public void stopTimer(View view) {
Toast.makeText(this, "Stopped...", Toast.LENGTH_SHORT).show();
}
}
I cannot seem to see why publishProgress does NOT fire from and I wanted to execute the ASyncTask from an button press.
I have 3 elements 2 buttons startTimer and stopTimer and 1 textview to update in the background.
Many thanks all.

Ty something like this :
protected class InitTask extends AsyncTask<Context, Integer, String> {
// -- run intensive processes here
// -- notice that the datatype of the first param in the class definition matches the param passed to this
// method
// -- and that the datatype of the last param in the class definition matches the return type of this method
#Override
protected String doInBackground(Context... params) {
// -- on every iteration
// -- runs a while loop that causes the thread to sleep for 50 milliseconds
// -- publishes the progress - calls the onProgressUpdate handler defined below
// -- and increments the counter variable i by one
int i = 0;
while (i <= 50) {
try {
Thread.sleep(50);
publishProgress(i);
i++;
}
catch (Exception e) {
Log.i("makemachine", e.getMessage());
}
}
return "COMPLETE!";
}
// -- gets called just before thread begins
#Override
protected void onPreExecute() {
Log.i("makemachine", "onPreExecute()");
super.onPreExecute();
}
// -- called from the publish progress
// -- notice that the datatype of the second param gets passed to this method
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
Log.i("makemachine", "onProgressUpdate(): " + String.valueOf(values[0]));
_percentField.setText((values[0] * 2) + "%");
_percentField.setTextSize(values[0]);
}
// -- called if the cancel button is pressed
#Override
protected void onCancelled() {
super.onCancelled();
Log.i("makemachine", "onCancelled()");
_percentField.setText("Cancelled!");
_percentField.setTextColor(0xFFFF0000);
}
// -- called as soon as doInBackground method completes
// -- notice that the third param gets passed to this method
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Log.i("makemachine", "onPostExecute(): " + result);
_percentField.setText(result);
_percentField.setTextColor(0xFF69adea);
_cancelButton.setVisibility(View.INVISIBLE);
}
}
}

Related

Why doesn't AsyncTask executes when the execute method is called using an instance but without the instance works fine? [duplicate]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I don't want to pass any arguments to doInBackground method of the AsyncTask.
So what should be the code like?
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
public class AsyncExample extends Activity{
private String url="http://www.google.co.in";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
new AsyncCaller().execute();
}
private class AsyncCaller extends AsyncTask<Void, Void, Void>
{
ProgressDialog pdLoading = new ProgressDialog(AsyncExample.this);
#Override
protected void onPreExecute() {
super.onPreExecute();
//this method will be running on UI thread
pdLoading.setMessage("\tLoading...");
pdLoading.show();
}
#Override
protected Void doInBackground(Void... params) {
//this method will be running on background thread so don't update UI frome here
//do your long running http tasks here,you dont want to pass argument and u can access the parent class' variable url over here
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
//this method will be running on UI thread
pdLoading.dismiss();
}
}
}
According to AsyncTask, its
AsyncTask<Params, Progress, Result>
Params, the type of the parameters sent to the task upon execution.
Progress, the type of the progress units published during the
background computation.
Result, the type of the result of the background computation.
So if you want to pass void in doInBackground just pass void in place of Params.
Example code:
class DownloadLink extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
//Do Your stuff here..
return null;
}
}
And call it as:
new DownloadLink().execute();
Create your AsyncTask class as if you don't want to pass any parameter to doInBackground :
public class LongOperation extends AsyncTask<Void, Void, String> {
public LongOperation(Context context) {
}
#Override
protected void onPreExecute() {
}
#Override
protected String doInBackground(Void... params) {
return null;
}
#Override
protected void onPostExecute(String result) {
}
}
and start AsyncTask as without passing any parameter to execute :
LongOperation longOperation = new LongOperation(this);
longOperation.execute();
Why don't you want to pass any arguments to it? You should explain...
This is how it usually works (example):
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
And to execute it you call:
new DownloadFilesTask().execute(url1, url2, url3);
Source: Android docs

How to get results of Async task in Android

I am trying AsyncTask. I cannot understand how to return the result.I am also confused on doInBackground() has return type Void . Why does it need return null; if I return null how will I get value from this method.
package com.example.shikkok_services;
import android.app.Dialog;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
public class MyTask extends AsyncTask<Void, Integer, Void> {
//progressBar holo UI te kaj kore tai Context dorkar tai MyTask e construtor decler korlam.Inner class hole eita dorkar silo na
Context context;
Handler handler;
Dialog dialog;
TextView txtprogrss;
ProgressBar progress;
Button btnCancel;
MyTask(Context context, Handler handler){
this.context=context;
this.handler=handler;
}
MyTask(Context context){
this.context=context;
this.handler=handler;
}
//--------------------------------onPreExecute()............................................
#Override
protected void onPreExecute() {
super.onPreExecute();
// create dialog
dialog=new Dialog(context);
dialog.setCancelable(true);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.pogressdialog);
dialog.show();
txtprogrss=(TextView) dialog.findViewById(R.id.txtProgress);
progress=(ProgressBar)dialog.findViewById(R.id.progressBar2);
btnCancel=(Button)dialog.findViewById(R.id.btnProgress);
//progress=new ProgressBar(context);
btnCancel.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
MyTask.this.cancel(true);
dialog.dismiss();
}
});
dialog.show();
}
//--------------------------------doInBackground()...........................
#Override
protected Void doInBackground(Void... arg0) {
//Kaj hobe backgournd e not UI e
// do tasks and update msg
for (int i = 0; i < 10; i++) {
if(isCancelled()){
break;
}else{
Log.e("In Background","current value;"+ i);
publishProgress(i);
//joto bar publishProgress() call hobe toto bar OnProgressUpdate hobe..
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
//------------------------------onProgressUpdate().....................................
#Override
protected void onProgressUpdate(Integer... values) {
//dowonload hole koto percent hosse seita dhore dhore UI te dekhalte parbo
super.onProgressUpdate(values);
// update dialog progress
progress.setProgress(values[0]);
txtprogrss.setText("progress update"+ values[0]+"%");
}
//-----------------------------OonPostExecute()...........................................
#Override
protected void onPostExecute(Void result) {
// jokhon kaj ses hoe jabe tokhon ei method e asben then UI te chole asben
super.onPostExecute(result);
// handler.sent message
dialog.dismiss();
Toast.makeText(context, "Finished", Toast.LENGTH_LONG).show();
}
}
I am also confuse doInBackground is return type Void .Why it is need return null; if I return null how get value from this method.please tell me.
This is because that is what you have made it. You can return a type you just have to change the class definition ex.
public class MyTask extends AsyncTask<Void, Integer, String> { // changed last param
With this, doInBackground() will be expected to return a String type to onPostExecute(). Which means you would also have to change that method to
#Override
protected void onPostExecute(String result) {
You would then obviously change your return statement in doInBackground() to return someString.
I used String as an example but you could change that.
As far as returning value after AsyncTask finishes
See this answer about using an interface. It is really easy to implement and will update your Activity when the task finishes.
Also please read (or re-read) the AsyncTask docs
AsyncTask must return null because you said so declaring this: AsyncTask<Void, Integer, Void>. The third parameter determines what doInBackground() returns and therefore what onPostExecute() gets.
Change this datatype to make it return whetever you want, this way you'll receive it as a parameter in the onPostExecute() method and you can even update Views in the main UI Thread from within this method (you can even update them from anywhere besides doInBackground()).
For getting value from asynchronous task call it like this:
String result= new MyTask ().execute().get();
class MyTask extends AsyncTask<String, String, String>
{
protected String doInBackground(String... params)
return somevalue;
}
}

Updating table from async task android

I'm following this tutorial
to learn how to make progress bars. I'm trying to show the progress bar on top of my activity and have it update the activity's table view in the background.
So I created an async task for the dialog that takes a callback:
package com.lib.bookworm;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
public class UIThreadProgress extends AsyncTask<Void, Void, Void> {
private UIThreadCallback callback = null;
private ProgressDialog dialog = null;
private int maxValue = 100, incAmount = 1;
private Context context = null;
public UIThreadProgress(Context context, UIThreadCallback callback) {
this.context = context;
this.callback = callback;
}
#Override
protected Void doInBackground(Void... args) {
while(this.callback.condition()) {
this.callback.run();
this.publishProgress();
}
return null;
}
#Override protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
dialog.incrementProgressBy(incAmount);
};
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(context);
dialog.setCancelable(true);
dialog.setMessage("Loading...");
dialog.setProgress(0);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setMax(maxValue);
dialog.show();
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
this.callback.onThreadFinish();
}
}
In My Activity:
final String page = htmlPage.substring(start, end).trim();
//Create new instance of the AsyncTask..
new UIThreadProgress(this, new UIThreadCallback() {
#Override
public void run() {
row_id = makeTableRow(row_id, layout, params, matcher); //ADD a row to the table layout.
}
#Override
public void onThreadFinish() {
System.out.println("FINISHED!!");
}
#Override
public boolean condition() {
return matcher.find();
}
}).execute();
So the above creates an async task to run to update a table layout activity while showing the progress bar that displays how much work has been done..
However, I get an error saying that only the thread that started the activity can update its views. I tried changing my Async Task's run to the following:
MainActivity.this.runOnUiThread(new Runnable() {
#Override public void run() {
row_id = makeTableRow(row_id, layout, params, matcher); //ADD a row to the table layout.
}
}
But this gives me synchronization errors.. Any ideas how I can display progress and at the same time update my table in the background?
Currently my UI looks like:
Whatever update that you are doing in the UI do it in progress update, use Global Variables to pass values or use Getter Setter.
Here is a simple example, from one of my current project.
It changes the width of the LinearLayout, which acts as progress bar and also updates the textview with X%. Am updating by calling onProgressUpdate
public class Updater extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
width = getWindowManager().getDefaultDisplay().getWidth();
Log.wtf(tag, "width" + width);
}
#Override
protected Void doInBackground(Void... params) {
while (updated < sleep) {
try {
Thread.sleep(updateEveryXmillSec);
updated = updated + updateEveryXmillSec;
publishProgress();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
mTextView.setText((int) (100 * updated / sleep) + " %");
xwidth = (width * ((int) (100 * updated / sleep)) / 100);
mLayout.setLayoutParams(new RelativeLayout.LayoutParams(xwidth,
height));
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
startActivity(new Intent(getApplicationContext(), Main.class));
finish();
}
}
Call new Updater().execute(); to trigger the action.
You should split your UI data from the Row Data. Make a RowObject which contains the data to display in the table:
class RowData {
String program;
String course;
String bookName;
// get/set etc
}
You can fill this object in the UIThreadProgress class run method and push it to a synced list.
In onProcessUpdate() you can than build the View Object based on the synced list and add it to the View Hierachie. You are on the UI thread now, and adding should be possible.
You have to care about a synced list during this. Because the Background Thread and the UI Thread will adding and removing objects at the same time. a synchronized will help here. Depending on the speed of your algorithm to calculate the needed data, a faster approach than the synced list is better. But the Idea is always the same. You have to split your data and the View Operations.

How to use AsyncTask correctly in Android [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I don't want to pass any arguments to doInBackground method of the AsyncTask.
So what should be the code like?
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
public class AsyncExample extends Activity{
private String url="http://www.google.co.in";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
new AsyncCaller().execute();
}
private class AsyncCaller extends AsyncTask<Void, Void, Void>
{
ProgressDialog pdLoading = new ProgressDialog(AsyncExample.this);
#Override
protected void onPreExecute() {
super.onPreExecute();
//this method will be running on UI thread
pdLoading.setMessage("\tLoading...");
pdLoading.show();
}
#Override
protected Void doInBackground(Void... params) {
//this method will be running on background thread so don't update UI frome here
//do your long running http tasks here,you dont want to pass argument and u can access the parent class' variable url over here
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
//this method will be running on UI thread
pdLoading.dismiss();
}
}
}
According to AsyncTask, its
AsyncTask<Params, Progress, Result>
Params, the type of the parameters sent to the task upon execution.
Progress, the type of the progress units published during the
background computation.
Result, the type of the result of the background computation.
So if you want to pass void in doInBackground just pass void in place of Params.
Example code:
class DownloadLink extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
//Do Your stuff here..
return null;
}
}
And call it as:
new DownloadLink().execute();
Create your AsyncTask class as if you don't want to pass any parameter to doInBackground :
public class LongOperation extends AsyncTask<Void, Void, String> {
public LongOperation(Context context) {
}
#Override
protected void onPreExecute() {
}
#Override
protected String doInBackground(Void... params) {
return null;
}
#Override
protected void onPostExecute(String result) {
}
}
and start AsyncTask as without passing any parameter to execute :
LongOperation longOperation = new LongOperation(this);
longOperation.execute();
Why don't you want to pass any arguments to it? You should explain...
This is how it usually works (example):
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
And to execute it you call:
new DownloadFilesTask().execute(url1, url2, url3);
Source: Android docs

How to do something after all asynchronous tasks finished?

I'm using AsyncTask to download some files, and want to do something after all tasks finished.
Is there any easy way to do this?
Keep track of how many async tasks you have running and do something when the total is 0.
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
public class MainActivity extends Activity {
public int numOfTasks = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
public void addTask(){
numOfTasks++;
}
public void removeTask(){
numOfTasks--;
}
public void allTasksComplete(){
if(numOfTasks ==0){
//do what you want to do if all tasks are finished
}
}
class RequestTask extends AsyncTask<String, String, String>{
#Override
protected String doInBackground(String... uri) {
String responseString = "";
return responseString;
}
#Override
protected void onPreExecute()
{
addTask(); // adds one to task count.
super.onPreExecute();
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
removeTask(); // subtracts one from task count.
allTasksComplete(); // checks to see if all tasks are done... task count is 0
}
}
}
AsyncTask has a callback method name onPostExecute. It will be execute when the background task finish.
You can use onPostExecute() callback when Asyn task finishes background processing, In a typical scenarion you would notify the UI (list adapter or UI Activity) that download of the File is finished and UI can refresh or populate the data.
onPreExecute(), invoked on the UI thread immediately after the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.
Please have a look at this Android Ref example:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
http://developer.android.com/reference/android/os/AsyncTask.html
Example2:
https://github.com/ashutoshchauhan13/TwitterFeedApp/blob/master/TwitterFeedApp/src/com/sixthsense/twitterfeed/ui/TwitterFeedActivity.java

Categories

Resources