Is there anyway to use AsyncTask without passing in any parameters? I am currently passing in an empty string, but I'm not doing anything with it:
DownloadWebPageTask task = new DownloadWebPageTask();
task.execute(new String[] { "" });
class DownloadWebPageTask extends AsyncTask<String, Void, String> {
private final ProgressDialog dialog = new ProgressDialog(MainScreen.this);
#Override
protected void onPreExecute() {
dialog.setMessage("Gathering data for\n"+selectedSportName+".\nPlease wait...");
dialog.show();
}
#Override
protected String doInBackground(String... urls) {
//go do something
return "";
}
#Override
protected void onPostExecute(String result) {
dialog.dismiss();
startTabbedViewActivity();
}
}
private void startTabbedViewActivity(){
Intent intent = new Intent(MainScreen.this, TabbedView.class);
intent.putExtra(SPORT_NAME_EXTRA, selectedSportName);
intent.putExtra(HEADLINES_FOR_SPORT_EXTRA, existingSportHeadlines.get(selectedSportName));
intent.putExtra(SCORES_FOR_SPORT_EXTRA, existingSportScores.get(selectedSportName));
intent.putExtra(SCHEDULE_FOR_SPORT_EXTRA, existingSportSchedule.get(selectedSportName));
startActivity(intent);
}
For some reason, when I run the code as shown, with nothing happening in doInBackground(), the dialog dissapears, and the TabbedView activity starts.
But, when I use doInBackground() to run some code, the dialog dissapears, but, the TabbedView activity won't start. So I'm wondering if I could be doing anything differently?
Yes you can use AsyncTask without passing a String to the doInBackground() method.
Just change the first and third generic types from String to Void:
class DownloadWebPageTask extends AsyncTask<Void, Void, Void> {
}
From the doc:
The three types used by an asynchronous task are the following:
1)Params, the type of the parameters sent to the task upon execution.
2)Progress, the type of the progress units published during the
3) background computation. Result, the type of the result of the
background computation.
For the signature of onPostExecutetry this:
#Override
protected void onPostExecute(Void unused) {
}
EDIT:
For the parameters it's actually very simple.
Consider this:
class MyTask extends AsyncTask<Type1, Type2, Type3> {
#Override
protected void onPreExecute() {
}
#Override
protected Type3 doInBackground(Type1... param) {
}
#Override
protected void onProgressUpdate(Type2... progress) {
}
#Override
protected void onPostExecute(Type3 result) {
}
}
In order to determine what Type1, Type2 and Type3 should be, you'll have to ask yourself 3 questions:
What parameter should I pass to my task? => Type1
What is the type of the intermediate results that need to be shown during processing? =>
Type2
What is the type of the resulting operation? => Type3
In your case, I don't know whether the URL that you are downloading data from is defined in a globally or you want to pass it to the task. If it's defined globally, then you don't Type1 should be Void.
If you want to pass it to the task, then you can pass it to the doInBackground() method and Type1 would be String.
Obviously for your case you don't need to worry about Type2 since you aren't publishing any intermediate results and since you aren't doing anything with the result in onPostExecute() then Type3 is Void too.
To summarize you'll have:
class DownloadWebPageTask extends AsyncTask<String, Void, Void> {
#Override
protected Void doInBackground(String... urls) {
// do something with urls[0]
}
#Override
protected void onPostExecute(Void unused) {
// dismiss pd and start new intent
}
}
Or:
class DownloadWebPageTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... unused) {
}
#Override
protected void onPostExecute(Void unused) {
// dismiss pd and start new intent
}
}
Depending on your needs. Is that clear enough?
You simple specify Void for AsyncTask generics
class DownloadWebPageTask extends AsyncTask<Void, Void, Void> {
Look at the AsyncTask generics section
Related
I am using an AsyncTask in an activity.
here is my code
public class MyActivity extends AppCompatActivity {
EditText editUserNameLogin;
EditText editPassLogin;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
//ButterKnife.bind(this);
editUserNameLogin = (EditText) findViewById(R.id.input_username_login);
editPassLogin = (EditText) findViewById(R.id.input_password_login);
}
public class AsyncTaskClass extends AsyncTask<String, String, String> {
String strUserName = editUserNameLogin.getText().toString();
String passLogin = editPassLogin.getText().toString();
#Override
protected void onPreExecute() {
}
#Override
protected String doInBackground(String... params) {
Toast.makeText(MyActivity.this, passLogin, Toast.LENGTH_SHORT).show();
}
#Override
protected void onPostExecute(String r) {
}
}
but in doInBackground can't get values passLogin or strUserName
(Toast.makeText(MyActivity.this, passLogin,) don't show any text)
Try and execute AsyncTaskClass in onCreate
new AsyncTaskClass().execute(); //use this method and call this in onCreate
Try this one, inside onCreate
String response="checking";
new AsyncTaskClass().execute(response);
then create inner class AsyncTaskClass,
private class AsyncTaskClass extends AsyncTask<String,Void,String > {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... strings) {
String respose1 = strings[0];
return respose1;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);}
}
You can not perform UI operation inside background AsyncTask doInBackground method because AsyncTask not work with current UI thread, its create new thread while you initialize and execute.
Let me explain you in bref.
While activity start its stay with Activity Thread and when you complete activity operation and destroy its completely remove from operation task.
But while you start AsyncTask on Activity its start with individual operation stat that not depends on activity that you start, so if you perform UI operation in doInBackground method and in case Activity destroyed and you working on UI that already destroyed by activity and UI cannot get reference, its generate an exception. So it's necessary to work with current activity thread not another background thread.
There are many case that you can pass data inside AsyncTask, i'm comfortable with below operation, it can help you also.
// Pass data to AsyncTask comma separated values
new MyBackgroundTask().execute("Hello there!","How are you?");
private class MyBackgroundTask extends AsyncTask<String, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(String... strings) {
String message1 = strings[0];
String message2 = strings[1];
Log.d("_TAG_", "First String: " + message1);
Log.d("_TAG_", "Second String: " + message2);
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
}
}
For more information read Android Official Documents AsyncTask Developer Guides
You cant show ui operations like toast in doInBackground if you still want to do that then use this code to display toast while in doInBackground
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this, "", Toast.LENGTH_SHORT).show();
}
});
and also you need to call yourAsyncTaskObject.execute to start asynctask
I have no idea what exactly you want to achieve by such behavior.
But i am pointing out some point here . First of all you can not access any UI element in background thread .
#Override
protected String doInBackground(String... params) {
Toast.makeText(MyActivity.this, passLogin, Toast.LENGTH_SHORT).show();
}
The above code is not going to work as doInBackground runs asynchronously separate from UI thread.
If you want to show a toast on AsyncTask started then do it in onPreExecute or after execution do it in onPostExecute.
#Override
protected void onPreExecute() {
Toast.makeText(MyActivity.this, passLogin, Toast.LENGTH_SHORT).show();
}
And as i see you never execute the AsyncTask then how are you expecting anything from it. Do call execute().
new AsyncTaskClass().execute();
For more on AsyncTask read AsyncTask.
Try the following:
#Override
protected String doInBackground(String... params) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MyActivity.this, passLogin, Toast.LENGTH_SHORT).show();
}
});
}
AsyncTask enables proper and easy use of the UI thread. This class
allows you to perform background operations and publish results on the
UI thread without having to manipulate threads and/or handlers.
new AsyncTaskClass("SEND STRING").execute();
You can pass this Your Value this way
private class AsyncTaskClass extends AsyncTask<String, String, String> {
String strRESPONSE="";
public MyAsyncTask(String str_GET) {
this.strRESPONSE=str_GET; // print "SEND STRING"
}
}
I am trying to work with Asynctask, but everytime I'm getting its status, it always returns running.
What is wrong in my code?
This is how I load my asynctask:
LongOperation LongOperation = new LongOperation(finalLink[0], download_data);
LongOperation.execute();
Toast.makeText(getApplicationContext(), LongOperation.getStatus().toString(), Toast.LENGTH_SHORT).show();
This is my asynctask:
private class LongOperation extends AsyncTask<Void, Void, Void> {
public Download_data download_data;
public String link;
public boolean loading;
public LongOperation(String link, Download_data download_data){
this.link = link;
this.download_data = download_data;
}
#Override
protected Void doInBackground(Void... params) {
download_data.download_data_from_link(link);
return null;
}
protected void onPostExecute() {
finish();
}
#Override
protected void onPreExecute() {
Toast.makeText(getApplicationContext(),"Executed.", Toast.LENGTH_LONG).show();
}
#Override
protected void onProgressUpdate(Void... values) {
}
}
Because you are checking status right after executing it:
LongOperation.execute();
Toast.makeText(getApplicationContext(), LongOperation.getStatus().toString(), Toast.LENGTH_SHORT).show();
AsyncTask runs on background thread. So right after calling execute() controls moves to display Toast. And by that time, task is still running.
You will receive finished status in onPreExecute of AsyncTask.
#Override
protected void onPostExecute(Void mVoid) {
Toast.makeText(getApplicationContext(), this.getStatus().toString(), Toast.LENGTH_SHORT).show();
finish();
}
In case you are confused about threads, do read this: Java Multithreading
The correct signature of onPostExecute() is really;
protected void onPostExecute (Result result)
Since you're not overriding the one in AsyncTask but defining another overload, it (and in its turn finish() is never called).
Fix the signature and it should complete as intended.
I am quite new to Android Development. I am working in a app where i need to make a lot of async calls to api. For each and every API call, I have to write the similar looking AsyncTask class over and over again. So, is there any way to make these Async Calls modular?
yes it is possible use Listener and AsyncTask with parameterized constructor
Check it
Create an interface
public interface OnTaskCompletListerner {
void oncompleteListerner(String name);
}
create an AsyncTask class as follows
public class AsyncTaskModuler extends AsyncTask<Void, Void, String> {
private Context context;
private HashMap<String, String> data;
private String URL;
private OnTaskCompletListerner taskdone;
public AsyncTaskModuler(Context ctx,HashMap<String, String> data,String url,OnTaskCompletListerner taskdone){
this.context=ctx;
this.data=data;
this.URL=url;
this.taskdone=taskdone;
}
#Override
protected String doInBackground(Void... params) {
//Do the task here and return the value if needed
return null;
}
#Override
protected void onPostExecute(String result) {
taskdone.oncompleteListerner(result);
}
and call it in your activity like this
public class CallAync extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String url="";
HashMap<String, String> data=new HashMap<String, String>();
AsyncTaskModuler moduler=new AsyncTaskModuler(CallAync.this, data, url, completListerner);
moduler.execute();
}
OnTaskCompletListerner completListerner=new OnTaskCompletListerner() {
#Override
public void oncompleteListerner(String name) {
}
};
}
Create an general async task and pass your url as param to it .Hence you can reuse the same async task for all your api calls
public class myTask extends AsyncTask<Void, Void, Void> {
String muUrl;
public myTask(Context context, Activity activity,
String url) {
contxt = context;
myUrl=url;
}
#Override
protected Void doInBackground(Void... params) {
makeApiCalls();
return null;
}
}
Start the task in the following way :
new myTask(this, this, urlStr).execute();
EDIT
How can I perform different logic onPostExecute() ?
You can add another param in the constructor of myTask.
Ex.
public MyTask(Context context, Activity activity,
String url,String postExecuteAction) {
}
In your post executes just check of each case in if else and perform the respective task
Dummy Background class
private class BackGroundClass extends AsyncTask<String, Void, Bitmap> //<arg to do InBackground,,returntype of do inBackground and arg of onPostExecut>
{
public BackGroundClass()
{
}
#Override
protected void onPreExecute() //forground work in UI thread prior to doInbackground
{
super.onPreExecute();
}
#Override
protected Bitmap doInBackground(String... urls) //background work in parallel thread
{
Bitmap b=null;
// your background work
return b;
}
#Override
protected void onPostExecute(Bitmap result) //forground work in UI thread post to doInbackground
{
super.onPostExecute(result);
if(result!=null)
{
//use bitmap image in result
}
else
{
//Image is not available
}
}
}
Calling for one parellel execution
new BackGroundClass().execute(StringArg1,stringArg2,StringArg3);
Calling for multiple parellel execution
when tou need to call more than one background task at same time
new BackGroundClass().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,StringArg1,stringArg2,StringArg3);
Called from single activity
use this as an inner class to your activity for making it easy to share variable if not called from more than one activity
Called from more than one activity
use constructor to pass activity context,and other variable
new BackGroundClass(constructor arguments).execute(StringArg1,stringArg2,StringArg3);
new BackGroundClass(constructor arguments).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,StringArg1,stringArg2,StringArg3);
Hi I'm making Login page that access MySQL database. But my Activity always runs the code that check fail/success before it finishes the AsyncTask.
I tried using asynctask.get() method, but it just freeze my UI and doesn't work.
I tried this answer that said I should call the result-checker method inside onPostExecute().
But since I need to change the TextView to show success/failed, it results in NullPointerException because I instantiate the TextView inside onCreate().
I can't move the TextView instantiation into constructor because it will return NullPointerException unable to instantiate activity ComponentInfo.
Login.java
public class Login extends Activity{
//declare global Views here
protected void onCreate(Bundle bundle){
//Setup views
}
protected void onClick(View v){
//Setup necessary variables
AsyncClass async = new AsyncClass(this);
async.execute(username, password);
}
public void checkSuccess(boolean success){
if(success)
textView1.setText("Success");
else
textView1.setText("Failed");
}
}
AsyncClass.java
public class AsyncClass extends AsyncTask<String, String, JSONObject>{
protected JSONObject doInBackground(String... params){
//access database
}
protected void onPostExecute(JSONObject json){
//read the json result
Login login = new Login();
login.checkSuccess(true);
}
}
Any solution? Thanks
How about making AsyncTask as your inner class?
So your code should look something like below.
public class Login extends Activity {
//declare global Views here
protected void onCreate(Bundle bundle) {
//Setup views
}
protected void onClick(View v) {
new AsyncClass().execute(username, password);
}
public void checkSuccess(boolean success) {
if (success) textView1.setText("Success");
else textView1.setText("Failed");
}
class AsyncClass extends AsyncTask < String, String, JSONObject > {
protected JSONObject doInBackground(String...params) {
//access database
}
protected void onPostExecute(JSONObject json) {
checkSuccess(true / false);
}
}
}
try this
protected void onPostExecute(JSONObject json){
//read the json result
Login login = (Login)context; // object that you pass to task constructor
login.checkSuccess(true);
}
Also you can add progress dialog to your task to indicate some job execution
public class BaseTask<T> extends AsyncTask<Object, Void, T> {
public Context context;
public ProgressDialog dialog;
public BaseTask(Context context) {
this.context = context;
this.dialog = new ProgressDialog(context);
}
#Override
protected void onPreExecute() {
this.dialog.setMessage(context.getResources().getString(R.string.loading));
this.dialog.show();
}
#Override
protected T doInBackground(Object... objects) {
//....
return something;
}
#Override
protected void onPostExecute(T result) {
if (dialog != null && dialog.isShowing())
dialog.dismiss();
// do something
}
}
You cannot edit the UI from the async task thread. In order to make updates to the UI thread, use the onProgressUpdate() method. This method is part of your AsyncTask class, is actually executed in the main UI Thread (I hope you use the async task as a nested class btw, since it is declared public I guess your not. You should change that). The onProgressUpdate() Method is called by the OS itself if you call publishProgress(...) inside your Async task.
A small sample:
protected JSONObject doInBackground(String... params){
publishProgress("test");
}
/**
* This method is part of the Async Task
*/
protected void onProgressUpdate(String... progress) {
login.checkSuccess(true);
}
I would use it this way, just override your onPostExecute where you need it or create a own interface
//create a object f your asyncclass and
//override the onPostExecute where you need it
mInfo = new ASYNCCLASS({
#Override
public void onPostExecute(Object result){
//doSomething something with your views!
}
}).execute();
Waiting is not the answer, because you do not know how long your Asynctask will take to end.
Code above is not tested, just pseudoce, but it should show what i mean.
Do not have my IDE round here, so if anybody would correct the brackets if neccessary would be great!
Greetz
Could anyone tell me what is going wrong here?
public class BackgroungTask extends AsyncTask<String, Void, Void> {
public Void doInBackground(String... params) {
//tasks
return; //error occurs here!
}
public void onPostExecute(Void result) {
//codes
}
}
The above class does not depend on return values. So onPostExceute() simply execute codes written in there.
Thanks in advance!
just return null.
public class BackgroungTask extends AsyncTask<String, Void, Void> {
public Void doInBackground(String... params) {
//tasks
return null;
}
public void onPostExecute(Void result) {
//codes
}
}
I think you have to use "return null;" instead of just "return;", as Void is a class around the usual "void" value.
In doInBackGround return null, as Void is an object (does not = void)..
public class BackgroungTask extends AsyncTask<String, Void, Void> {
public Void doInBackground(String... params) {
//tasks
return null; //error occurs here!
}
public void onPostExecute(Void result) {
//codes
}
}
AsyncTask works like this
onPreExecute -> doInBackGround -> onPostExecute
Neglecting progressUpdates etc, as soon doInBackGround is complete, control goes to onPostExecute. A simple return disrupts this flow hence causing the error. To Solve this, replace with return null Since its a void. The return statement parameters are passed to onPostExecute as parameter, where you can use it to see wheter it has been successful.
doInBackGround returns null value
public class BackgroungTask extends AsyncTask<String, Void, Void> {
....
....
}
check this Android dev doc for asynchronous task in andorid