I'm developing an app that when user clicks on a Button it executes an Asynctask that this class calls a method at it's onPostExecute method that calls another Asynctask! It works when user clicks once, but at the second time it crashes and says Cannot execute task: the task has already been executed (a task can be executed only once)
.
public class Test extends Activity {
A a;
B b;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
Button btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
a = new A();
a.execute();
}
});
}
class A extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... arg0) {
// doing st
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
runB();
a.cancel(true);
}
}
public void runB() {
b = new B();
b.execute();
}
class B extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... arg0) {
// doing st
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
//doing st
b.cancel(true);
}
}
Use AsyncTask.Status for checking status of AsyncTask before calling AsyncTask.execute() method on Button onClick:
#Override
public void onClick(View arg0) {
if(a ==null){
a = new A();
a.execute();
}
}
And in onPostExecute of B class assign null to a :
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
//doing st
b.cancel(true);
a=null;
}
Related
I'm facing a problem: I created two Activities.
One is the main Activity, which has a Button.
When I click this Button, the second Activity starts.
The second Activity uses an Asynctask in which a number is incremented from 1 to 10 and displays this number in a Textview
What I'm facing is that when I click the back Button while the Asynctask has not completed and then again go to the second Activity the Asynctask is not run from start immediately.
I know because in background when it completed the old task then it again starts a new task. Is there a way to fix this when destroying the Activity it also destroy the Asynctask?
Here is video sample for my problem.
Code for Main Activity:
public class MainActivity extends AppCompatActivity {
Button bt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt = (Button) findViewById(R.id.bt);
bt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(MainActivity.this,SecondAcitivity.class);
startActivity(i);
}
});
}
}
Code of Second Activity:
public class SecondAcitivity extends AppCompatActivity {
TextView t1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second_acitivity);
t1 = (TextView) findViewById(R.id.t1);
OurWork obj = new OurWork();
obj.execute();
}
class OurWork extends AsyncTask<Void, Integer, String> {
#Override
protected String doInBackground(Void... params) {
int i = 0;
while (i < 11) {
try {
Thread.sleep(700);
publishProgress(i);
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "Successfully Completed";
}
#Override
protected void onProgressUpdate(Integer... values) {
t1.setText(values[0] + "%");
}
#Override
protected void onPostExecute(String result) {
t1.setText(result);
}
}
}
you need to cancel the task on back pressed, and you need to monitor if the task is canceled while executing the doInbackground().
1- override onbackpressed:
#Override
public void onBackPressed() {
obj.cancel(true); // where obj is the asyncTask refernce object name
super.onBackPressed();
}
2- monitor isCanceled()
#Override
protected String doInBackground(Void... params) {
int i = 0;
while (i < 11 && !isCancelled()) { // added !isCancelled()
try {
Thread.sleep(700);
publishProgress(i);
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "Successfully Completed";
}
on next iteration of the while loop, after cancel(true); is called,the loop will quit, and doInBackground() will return.
When you press back button , onBackPressed callback is called. so you can basically try this :
#Override
public void onBackPressed() {
if (asyncFetch.getStatus() == AsyncTask.Status.RUNNING) {
asyncFetch.cancel(true);
}
finish();
}
Try to use :
private OurWork task;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second_acitivity);
t1 = (TextView) findViewById(R.id.t1);
task = new OurWork();
task.execute();
}
#Override
public void onBackPressed() {
task.cancel(true);
super.onBackPressed();
}
AsyncTask runs in background of the activity where it was hosted. If OnPause or OnDestroy is called, AsyncTask is destroyed, so to solve this issue, Override OnResume and execute AsyncTask again.
To cancel the asyncTask even when it is running when back is pressed, add this to onBackPressed:
public class SecondAcitivity extends AppCompatActivity {
TextView t1;
static OurWork obj;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second_acitivity);
t1 = (TextView) findViewById(R.id.t1);
obj = new OurWork();
obj.execute();
}
class OurWork extends AsyncTask<Void, Integer, String> {
#Override
protected String doInBackground(Void... params) {
int i = 0;
while (i < 11) {
try {
Thread.sleep(700);
publishProgress(i);
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "Successfully Completed";
}
#Override
protected void onProgressUpdate(Integer... values) {
t1.setText(values[0] + "%");
}
#Override
protected void onPostExecute(String result) {
t1.setText(result);
}
}
//override onBackPressed and do this
#Override
public void onBackPressed() {
if (obj!=null && (obj.getStatus()== AsyncTask.Status.RUNNING ||
obj.getStatus()== AsyncTask.Status.PENDING ))
obj.cancel(true);
super.onBackPressed();
}
}
I have an AsyncTask that is created in onCreate() it is called GatherText() I have an animation that slides a TextView out of view. When that animation ends I want it to call the AsyncTask.
Here is a basic idea of my code
public class MainActivity extends Activity implements AnimationListener {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
class GatherText extends AsyncTask<JSONObject, String, JSONObject> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
}
#Override
protected void onPostExecute(JSONObject json) {
}//end onPostExecute
}//end GatherText Asynctask
}//end onCreate
#Override
public void onAnimationEnd(Animation animation) {
if(animation == slideout){
//THIS IS WHERE THE ERROR OCCURS
new GatherText().execute();
}
}//End onAnimationEnd
}//end Main Activity
In the onAnimationEnd() method I receive an error that says GatherText() can not be resolved to a type. How can I call GatherText() outside of onCreate?
Put your asynctask class outside of onCreate
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}//end onCreate
class GatherText extends AsyncTask<JSONObject, String, JSONObject> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
}
#Override
protected void onPostExecute(JSONObject json) {
}//end onPostExecute
}//end GatherText Asynctask
#Override
public void onAnimationEnd(Animation animation) {
if(animation == slideout){
gathertext = new GatherText();
new GatherText().execute();
}
}//End onAnimationEnd
As below code shows I have a function named record() I want to call this function with asynctask but I do not know how to work with asynctask, record function takes long to do some tasks so I need to use asynktsak.
public class Record extends Activity {
MediaPlayer mp;
String name;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.record);
mp = new MediaPlayer();
record();
}
public void record() {
.
.
.
}
}
Try this-
public class Record extends Activity {
MediaPlayer mp;
String name;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.record);
mp = new MediaPlayer();
new Task1().execute();
}
class Task1 extends AsyncTask<Void, Void, String> {
#Override
protected void onPreExecute()
{
super.onPreExecute();
}
#Override
protected String doInBackground(Void... arg0)
{
//Record method
}
#Override
protected void onPostExecute(String result)
{
super.onPostExecute(result);
}
}
}
Make AsyncTask Class and write code there and call your AsyncTask Class by new AsyncTaskClass().execute();
Try below code for your reference.
public void record() {
new AsyncTask<Void, Void, Void() {
#Override
protected void doInBackground(Void... params) {
}
Override
protected void onPostExecute(ArrayList<HashMap<String, String>> result) {
}
}.execute();
}
When I call only wpCategories = JsonToElement.getllAllCategory(); in the buttons onClick methood it works fine. (wpCategories get filled with data). But when I put this in a asynctask, wpCategories returns null. (is the doInBackground not being called?)
Here is my buttons on click methood:
public void onImageGridClick(View view) {
new GetJsonElementTask().execute();
Intent intent = new Intent(this, CategoryGridActivity.class);
intent.putParcelableArrayListExtra(Extra.IMAGES, wpCategories);
startActivity(intent);
}
And the asyncTask:
private class GetJsonElementTask extends AsyncTask<Void, Integer, String> {
#Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(HomeActivity.this, "",
"Loading...");
}
#Override
protected String doInBackground(Void... arg0) {
wpCategories = JsonToElement.getllAllCategory();
return null;
}
#Override
protected void onPostExecute(String value) {
progressDialog.dismiss();
}
#Override
protected void onProgressUpdate(Integer... progress) {
Log.v("DEBUG_LOG", "In onProgressUpdate");
}
}
Start your Activity inside onPostExecute because this method execute after doInBackground execution complete :
#Override
protected String doInBackground(Void... arg0) {
wpCategories = JsonToElement.getllAllCategory();
return wpCategories; //<<< return value from here
}
#Override
protected void onPostExecute(String value) {
progressDialog.dismiss();
Intent intent = new Intent(this, CategoryGridActivity.class);
intent.putParcelableArrayListExtra(Extra.IMAGES, value);
startActivity(intent);
}
Try following
public void onImageGridClick(View view) {
new GetJsonElementTask().execute();
}
public void startCategoryGridActivity(){
Intent intent = new Intent(this, CategoryGridActivity.class);
intent.putParcelableArrayListExtra(Extra.IMAGES, wpCategories);
startActivity(intent);
}
And the asyncTask:
private class GetJsonElementTask extends AsyncTask<Void, Integer, String> {
#Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(HomeActivity.this, "",
"Loading...");
}
#Override
protected String doInBackground(Void... arg0) {
wpCategories = JsonToElement.getllAllCategory();
return null;
}
#Override
protected void onPostExecute(String value) {
progressDialog.dismiss();
startCategoryGridActivity();
}
#Override
protected void onProgressUpdate(Integer... progress) {
Log.v("DEBUG_LOG", "In onProgressUpdate");
}
}
I have a string that I want to update using AsyncTask class
here is my code:
public class MainActivity extends Activity{
private String str = "oldString";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
getString();
}
private void getString(){
new CustomTask().execute();
}
private class CustomTask extends AsyncTask<Void, Void, String>{
#Override
protected String doInBackground(Void... params) {
// TODO Auto-generated method stub
Log.i("Lesson3", "doInBackground method");
str = "newString";
return "someString";
}
protected void onPostExecute(String s){
Log.i("Lesson3", "onPostExecute method");
}
}
onPostExecute method is not called, thats the problem??
Thanks
Answer is simple,
#Override
protected void onPostExecute(String s){
Log.i("Lesson3", "onPostExecute method");
}
You forgot your #Override the execute calls onPostExecute of the super class since it has not been overridden as yet.
public class MainActivity extends Activity {
private String str = "oldString";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
getString();
}
private void getString() {
new CustomTask().execute();
}
private void postExecuteCallback() {
Log.i("Lesson3", "String after callback: " + str );
}
private class CustomTask extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
// TODO Auto-generated method stub
Log.i("Lesson3", "doInBackground method");
str = "newString";
return "someString";
}
protected void onPostExecute(String s) {
Log.i("Lesson3", "onPostExecute method");
postExecuteCallback();
}
}
}
Why have you decided it doesn't run? Following code works just fine (fixed syntax errors in yours):
package com.stackoverflow;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
public class Test extends Activity {
private String str = "oldString";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
getString();
}
private void getString() {
new CustomTask().execute();
}
private class CustomTask extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
// TODO Auto-generated method stub
Log.i("Lesson3", "doInBackground method");
str = "newString";
return "someString";
}
protected void onPostExecute(String s) {
Log.i("Lesson3", "onPostExecute method");
}
}
}
How about having our own AsyncTask ?
Please have a look.
public abstract class CustomAsyncTask<Params, Progress, Result> {
private boolean isFinished = false;
private Result res;
protected void onPreExecute() {
}
protected void onPostExecute(Result result) {
}
protected void onProgressUpdate(Progress progress) {
}
protected abstract Result doInBackground(Params...params);
private void CheckAndUpdateUI()
{
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if(isFinished)
{
onPostExecute(res);
}
else
CheckAndUpdateUI();
}
},500);
}
public void execute(final Params...params)
{
onPreExecute();
//
CheckAndUpdateUI();
isFinished = false;
//
new Thread(new Runnable() {
#Override
public void run() {
res = doInBackground(params);
isFinished = true;
}
}).start();
}
}