I have called an async task from my button click.In the doInBackground I have called an API and It is returning me a Json object.I want to pass the Json object to another activity on the button click.How can I can get the return Json object value so that I can send it to other activity.
Thanks.
Create Interface
public interface Listener {
void success(BaseModel baseModel);
void fail(String message);
}
Create Base model class
public class BaseModel implements Serializable {
private static final long serialVersionUID = 1L;
}
Call below method inside your onClick mehtod.
protected void userLoginData(final String userName) {
// if you want to pass multiple data to server like string or json you can pass in this constructor
UserLoginLoader userLoginLoader = new UserLoginLoader(LoginActivity.this, userName, "1234567899", new Listener() {
#Override
public void success(BaseModel baseModel) {
// here you got response in object you can use in your activity
UserLoginModel userLoginModel = (UserLoginModel) baseModel;
// you can get data from user login model
}catch(Exception exception){
exception.printStackTrace();
Utils.showAlertDialog(LoginActivity.this, "Server is not responding! Try Later.");
}
}
#Override
public void fail(String message) {
}
});
userLoginLoader.execute();
}
:- User Login Loader class
public class UserLoginLoader extends AsyncTask<String, Void, Boolean> {
private Dialog dialog;
private Listener listner;
private String deviceId;
Activity activity;
String message;
String userName;
boolean checkLoginStatus;
public UserLoginLoader(Activity activity,String userName, String deviceId, Listener listener) {
this.listner = listener;
this.userName =userName;
this.activity = activity;
this.deviceId = deviceId;
}
#Override
protected Boolean doInBackground(String... arg0) {
//User login web service is only for making connection to your API return data into message string
message = new UserLoginWebService().getUserId(userName, deviceId);
if (message != "null" && !message.equals("false")) {
return true;
}
return false;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new Dialog(activity, R.style.CustomDialogTheme);
dialog.setContentView(R.layout.progress);
dialog.setCancelable(false);
dialog.show();
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
BaseModel baseModel = null;
if (!message.equals("null") && (!message.equals("false")) )
baseModel = parseData(message, result);
if (dialog.isShowing()) {
dialog.dismiss();
dialog.cancel();
dialog = null;
}
if (listner != null) {
if (result && baseModel != null)
listner.success(baseModel);
else
listner.fail("Server not responding! Try agian.");
} else
listner.fail("Server not responding! Try agian.");
}
//call parser for parsing data return data from the parser
private BaseModel parseData(String responseData, Boolean success) {
if (success == true && responseData != null
&& responseData.length() != 0) {
UserLoginParser loginParser = new UserLoginParser(responseData);
loginParser.parse();
return loginParser.getResult();
}
return null;
}
}
This is you Login parser class
public class UserLoginParser {
JSONObject jsonObject;
UserLoginModel userLoginModel;
/*stored data into json object*/
public UserLoginParser(String data) {
try {
jsonObject = new JSONObject(data);
} catch (JSONException e) {
Log.d("TAG MSG", e.getMessage());
e.printStackTrace();
}
}
public void parse() {
userLoginModel = new UserLoginModel();
try {
if (jsonObject != null) {
userLoginModel.setUser_name(jsonObject.getString("user_name")== null ? "": jsonObject.getString("user_name"));
userLoginModel.setUser_id(jsonObject.getString("user_id") == null ? "" : jsonObject.getString("user_id"));
userLoginModel.setFlag_type(jsonObject.getString("flag_type") == null ? "" : jsonObject.getString("flag_type"));
} else {
return;
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
/*return ship name list which is stored into model */
public UserLoginModel getResult() {
return userLoginModel;
}
}
Write a callback method in the Activity that takes in the argument that you wish to pass from AsyncTask to that Activity. Send reference to the Activity to AysncTask while creating it. From doInBackground() method make a call to this callback method with the data your API returns.
Code would be something like -
public class TestAsyncTask extends AsyncTask<Integer, Integer, String[]> {
Activity myActivity;
public TestAsyncTask(Activity activity) {
this.myActivity = activity;
}
#Override
protected String[] doInBackground(Integer... params) {
String data = yourApi();
myActivity.callback(data);
}
}
public class MyActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
new TestAsyncTask(this).execute(someId);
}
public void callback(String data) {
//process data
}
}
Just for the record you can directly get return value from doInBackground() method by calling get() on it.
String data = new TestAsyncTask(this).execute(someId).get();
But note this may block your UI thread as it will wait for the doInBackground() method to complete it's execution.
I have a serious problem which I can't a solution to.
I need to authenticate a token in order to let the user login into my app, the problem is that even though I'm using the AsyncTask, and probably because of it, I can't authenticate it in time. Other problem that sometimes accurs is that I get the NetworkOnMainThreadException error... I'm really hopeless.
Here's the flow -
Check for existsing token -> Validate -> Move to next activity
And here's my code -
public boolean validateToken(TokenAccess token) {
new IsValid().execute(token);
return isValid;
}
private class IsValid extends AsyncTask<TokenAccess, Void, Boolean> {
#Override
protected Boolean doInBackground(TokenAccess... params) {
TokenAccess token = params[0];
switch (token.getSource().getSource()) {
case 'M':
new UrlDownloader(new UrlDownloader.DownloadListener() {
#Override
public void setRequest(HttpRequest request) {}
#Override
public void onRecive(String content) {
if (content.contains("stats")) {
isValid = true;
} else {
isValid = false;
}
}
#Override
public void onError(Exception e) {}
}, UrlDownloader.RequestType.GET)
.execute("https://api.meetup.com/dashboard?access_token="
+ token.getToken());
}
return isValid;
}
}
That's is the URLDownloader class -
public class UrlDownloader extends AsyncTask<String, Void, HttpResponse> {
public static final String TAG = "net.ytsweb.socigo.assests.UrlDownloader";
public enum RequestType {
GET, POST;
}
private RequestType type;
private DownloadListener listener;
public UrlDownloader(DownloadListener listener, RequestType type) {
this.type = type;
this.listener = listener;
}
#Override
protected HttpResponse doInBackground(String... params) {
HttpClient httpClient = new DefaultHttpClient();
HttpUriRequest request;
HttpResponse response;
if (type == RequestType.GET) {
request = new HttpGet(params[0]);
} else {
request = new HttpPost(params[1]);
}
listener.setRequest(request);
try {
response = httpClient.execute(request);
} catch (Exception e) {
listener.onError(e);
return null;
}
return response;
}
#Override
protected void onPostExecute(HttpResponse response) {
try {
Log.d(TAG, response.getAllHeaders()[0].getValue() + "");
listener.onRecive(EntityUtils.toString(response.getEntity()));
} catch (Exception e) {
listener.onError(e);
}
}
public interface DownloadListener {
public void onRecive(String content);
public void onError(Exception e);
public void setRequest(HttpRequest request);
}
}
You need to use onPostExecute for handling the result of the IsValid AsyncTask. What I don't understand: why two AsyncTasks? One would be enough, do everything in there, and handle the result in the one and only onPostExecute.
Whatever happens in doInBackground is in a separate thread, onPostExecute happens on the UI-thread again. One AsyncTask is enough, but don't fetch a result in your validateToken method. In there, just execute your AsyncTask and whatever you need to do with the result you have to initiate in the onPostExecute.
As a basic example of what I mean:
public boolean validateToken(TokenAccess token) {
new YourAsyncTask().execute(token);
// DON'T rely on a result here
}
public class YourAsyncTask extends AsyncTask<?, ?, ?> {
#Override
protected ? doInBackground(?) {
// do networking in background-task
return result;
}
#Override
protected void onPostExecute(? response) {
// handle result here.. call a method in your main class, a listener with the result, or start an Activity directly
}
}
I'm making an android application which downloads JSON file in the AsyncTask class after SEARCH BUTTON in Activity is clicked. And I want to display Progress Dialog on the Activity while downloading data. But on my AVD and device, actual action is different from my thought. See this video (about 1 minute) I uploaded. https://www.youtube.com/watch?v=qKyVGZ1FxIo&feature=youtube_gdata_player
In this video,after SEARCH BUTTON clicked the UI freeze for a while, and then ProgressDialog is shown for a very short moment and Toast is shown.
I want ProgressDialog to be shown right after click, and be dismissed right before Toast is shown.
ClickListner in Activity:
#Override
public void onClick(View v) {
DownloadJSONFile task = new DownloadJSONFile(MainActivity.this);
task.execute("1", "class", lectureName, teacherName, date, period, "");
}
AsyncTask:
import org.json.JSONArray;
import com.fc2.wiki.ap2012.komari.SearchResultActivity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.widget.Toast;
public class DownloadJSONFile extends AsyncTask<String, Integer, JSONArray> {
private ProgressDialog dialog;
Context context;
JSONArray jsonArray;
boolean makeNewActivityFlag = true;
public DownloadJSONFile(Context context, boolean flag) {
this.context = context;
this.makeNewActivityFlag = flag;
}
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(this.context);
dialog.setTitle("こまり"); //it's Japanese
dialog.setMessage("通信中…");
dialog.setIndeterminate(true);
dialog.setCancelable(true);
dialog.show();
}
doInBackground:
#Override
protected JSONArray doInBackground(String... keywords) {
try {
//for test
while(!this.dialog.isShowing()){
Thread.sleep(500);
}
//I will load JSON file here
/*
JSONArray jsonArray = UTaisakuDatabaseUtil.getInstance()
.getJSONSearchResult(version, method, searchedLectureName,
searchedTeacherName, date, period, assessment);
*/
//for test
Thread.sleep(5000);
} catch (NumberFormatException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
} catch (InterruptedException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
return jsonArray;
}
onPostExecute:
#Override
protected void onPostExecute(JSONArray jsonArray) {
this.jsonArray = jsonArray;
if (this.dialog.isShowing())
dialog.dismiss();
if (this.makeNewActivityFlag) {
// Intentを作成してSearchResultActivityへ
if (jsonArray != null) {
Intent intent = new Intent(this.context,
SearchResultActivity.class);
intent.putExtra("LECTURE_NAME", searchedLectureName);
intent.putExtra("TEACHER_NAME", searchedTeacherName);
intent.putExtra("YOUBI", searchedDateString);
intent.putExtra("PERIOD", searchedPeriodString);
intent.putExtra("JSONARRAY", jsonArray.toString());
context.startActivity(intent);
} else
//in this test case,jsonArray is always null.So this Toast is always called
Toast.makeText(context, "ファイルが取得できませんでした。", Toast.LENGTH_SHORT)
.show();
}
}
}
Any ideas?
I found a solution of my own problem! I used Context class in a field parameta of AsyncTask. I use Activity class instead of Context!All things are work fine.
public class DownloadJSONFile extends AsyncTask<String, Integer, JSONArray> {
private ProgressDialog dialog;
//this is the cause of bug
//Context context;
//this is the answer
Activity activity;
JSONArray jsonArray;
boolean makeNewActivityFlag = true;
public DownloadJSONFile(Activity activity, boolean flag) {
this.activity = activity;
this.makeNewActivityFlag = flag;
}
…
…
}
But I can't explain why it's work fine when using Activity class and not work fine when using Context class.Can someone explain this? If you have any ideas,please comment here.
Thanks for posting the solution, I had similar problem adopting the code taken from zxing/BarCodeReader. After removing the context from constructor parameters, sleeping is interrupted properly and does not stall the UI thread anymore:
AutoFocusManager(Context context, Camera camera) {
this.camera = camera;
taskExec = new AsyncTaskExecManager().build();
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
String currentFocusMode = camera.getParameters().getFocusMode();
useAutoFocus =
FOCUS_MODES_CALLING_AF.contains(currentFocusMode);
Log.i(TAG, "Current focus mode '" + currentFocusMode + "'; use auto focus? " + useAutoFocus);
start();
}
protected Object doInBackground(Object... voids) {
try {
Thread.sleep(AUTO_FOCUS_INTERVAL_MS);
} catch (InterruptedException e) {
// continue
}
synchronized (AutoFocusManager.this) {
if (active) {
start();
}
}
return null;
}
I was reading about AsyncTask, and I tried the simple program below. But it does not seem to work. How can I make it work?
public class AsyncTaskActivity extends Activity {
Button btn;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener((OnClickListener) this);
}
public void onClick(View view){
new LongOperation().execute("");
}
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
for(int i=0;i<5;i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");
return null;
}
#Override
protected void onPostExecute(String result) {
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(Void... values) {
}
}
}
I am just trying to change the label after 5 seconds in the background process.
This is my main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="false"
android:max="10"
android:padding="10dip">
</ProgressBar>
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start Progress" >
</Button>
<TextView android:id="#+id/output"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Replace"/>
</LinearLayout>
My full answer is here, but here is an explanatory image to supplement the other answers on this page. For me, understanding where all the variables were going was the most confusing part in the beginning.
Ok, you are trying to access the GUI via another thread. This, in the main, is not good practice.
The AsyncTask executes everything in doInBackground() inside of another thread, which does not have access to the GUI where your views are.
preExecute() and postExecute() offer you access to the GUI before and after the heavy lifting occurs in this new thread, and you can even pass the result of the long operation to postExecute() to then show any results of processing.
See these lines where you are later updating your TextView:
TextView txt = findViewById(R.id.output);
txt.setText("Executed");
Put them in onPostExecute().
You will then see your TextView text updated after the doInBackground completes.
I noticed that your onClick listener does not check to see which View has been selected. I find the easiest way to do this is via switch statements. I have a complete class edited below with all suggestions to save confusion.
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings.System;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.view.View.OnClickListener;
public class AsyncTaskActivity extends Activity implements OnClickListener {
Button btn;
AsyncTask<?, ?, ?> runningTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = findViewById(R.id.button1);
// Because we implement OnClickListener, we only
// have to pass "this" (much easier)
btn.setOnClickListener(this);
}
#Override
public void onClick(View view) {
// Detect the view that was "clicked"
switch (view.getId()) {
case R.id.button1:
if (runningTask != null)
runningTask.cancel(true);
runningTask = new LongOperation();
runningTask.execute();
break;
}
}
#Override
protected void onDestroy() {
super.onDestroy();
// Cancel running task(s) to avoid memory leaks
if (runningTask != null)
runningTask.cancel(true);
}
private final class LongOperation extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// We were cancelled; stop sleeping!
}
}
return "Executed";
}
#Override
protected void onPostExecute(String result) {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed"); // txt.setText(result);
// You might want to change "executed" for the returned string
// passed into onPostExecute(), but that is up to you
}
}
}
I'm sure it is executing properly, but you're trying to change the UI elements in the background thread and that won't do.
Revise your call and AsyncTask as follows:
Calling Class
Note: I personally suggest using onPostExecute() wherever you execute your AsyncTask thread and not in the class that extends AsyncTask itself. I think it makes the code easier to read especially if you need the AsyncTask in multiple places handling the results slightly different.
new LongThread() {
#Override public void onPostExecute(String result) {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText(result);
}
}.execute("");
LongThread class (extends AsyncTask):
#Override
protected String doInBackground(String... params) {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "Executed";
}
Concept and code here
I have created a simple example for using AsyncTask of Android. It starts with onPreExecute(), doInBackground(), publishProgress() and finally onProgressUpdate().
In this, doInBackground() works as a background thread, while other works in the UI Thread. You can't access an UI element in doInBackground(). The sequence is the same as I have mentioned.
However, if you need to update any widget from doInBackground, you can publishProgress from doInBackground which will call onProgressUpdate to update your UI widget.
class TestAsync extends AsyncTask<Void, Integer, String> {
String TAG = getClass().getSimpleName();
protected void onPreExecute() {
super.onPreExecute();
Log.d(TAG + " PreExceute","On pre Exceute......");
}
protected String doInBackground(Void...arg0) {
Log.d(TAG + " DoINBackGround", "On doInBackground...");
for (int i=0; i<10; i++){
Integer in = new Integer(i);
publishProgress(i);
}
return "You are at PostExecute";
}
protected void onProgressUpdate(Integer...a) {
super.onProgressUpdate(a);
Log.d(TAG + " onProgressUpdate", "You are in progress update ... " + a[0]);
}
protected void onPostExecute(String result) {
super.onPostExecute(result);
Log.d(TAG + " onPostExecute", "" + result);
}
}
Call it like this in your activity:
new TestAsync().execute();
Developer Reference Here
Move these two lines:
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");
out of your AsyncTask's doInBackground method and put them in the onPostExecute method. Your AsyncTask should look something like this:
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
try {
Thread.sleep(5000); // no need for a loop
} catch (InterruptedException e) {
Log.e("LongOperation", "Interrupted", e);
return "Interrupted";
}
return "Executed";
}
#Override
protected void onPostExecute(String result) {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText(result);
}
}
How to memorize the parameters used in AsyncTask?
Don't
If you are new to AsyncTask then it is very common to get confused while writing an AsyncTask. The main culprits are the parameters used in the AsyncTask, i.e., AsyncTask<A, B, C>. Based on the A, B, C (arguments) signature of the methods differs which makes things even more confusing.
Keep it simple!
The key is don't memorize. If you can visualize what your task really needs to do then writing the AsyncTask with the correct signature at the first attempt would be a piece of cake. Just figure out what your Input, Progress, and Output are, and you will be good to go.
So what is an AsyncTask?
AsyncTask is a background task that runs in the background thread. It takes an Input, performs Progress and gives an Output.
I.e., AsyncTask<Input, Progress, Output>.
For example:
What is the relationship with methods?
Between AsyncTask and doInBackground()
doInBackground() and onPostExecute(),onProgressUpdate()` are also
related
How to write that in the code?
DownloadTask extends AsyncTask<String, Integer, String>{
// Always same signature
#Override
public void onPreExecute()
{}
#Override
public String doInbackGround(String... parameters)
{
// Download code
int downloadPerc = // Calculate that
publish(downloadPerc);
return "Download Success";
}
#Override
public void onPostExecute(String result)
{
super.onPostExecute(result);
}
#Override
public void onProgressUpdate(Integer... parameters)
{
// Show in spinner, and access UI elements
}
}
How will you run this Task?
new DownLoadTask().execute("Paradise.mp3");
Background / Theory
AsyncTask allows you to run a task on a background thread, while publishing results to the UI thread.
The user should always able to interact with the app so it is important
to avoid blocking the main (UI) thread with tasks such as
downloading content from the web.
This is why we use an AsyncTask.
It offers a straightforward interface by wrapping the UI thread message queue and handler that allow you to send and process runnable objects and messages from other threads.
Implementation
AsyncTask is a generic class. (It takes parameterized types in its constructor.)
It uses these three generic types:
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.
Not all types are always used by an asynchronous task. To mark a type as unused, simply use the type Void:
private class MyTask extends AsyncTask<Void, Void, Void> { ... }
These three parameters correspond to three primary functions you can override in AsyncTask:
doInBackground(Params...)
onProgressUpdate(Progress...)
onPostExecute(Result)
To execute AsyncTask
Call execute() with parameters to be sent to the background task.
What Happens
On main/UI thread, onPreExecute() is called.
To initialize something in this thread. (E.g. show a progress bar on the user interface.)
On a background thread, doInBackground(Params...) is called.
(Params were passed via execute.)
Where the long-running task should happen.
Must override at least doInBackground() to use AsyncTask.
Call publishProgress(Progress...) to update the user interface with a display of progress (e.g. UI animation or log text printed) while the background computation is still executing.
Causes onProgressUpdate() to be called.
On the background thread a result is returned from doInBackground().
(This triggers the next step.)
On main/UI thread, onPostExecute() is called with the returned result.
Examples
In both examples the "blocking task" is a download from the web.
Example A downloads an image and displays it in an ImageView, while
Example B downloads some files.
Example A
The doInBackground() method downloads the image and stores it in an object of type BitMap. The onPostExecute() method takes the bitmap and places it in the ImageView.
class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bitImage;
public DownloadImageTask(ImageView bitImage) {
this.bitImage = bitImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mBmp = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mBmp = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mBmp;
}
protected void onPostExecute(Bitmap result) {
bitImage.setImageBitmap(result);
}
}
Example B
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");
}
}
Example B execution
new DownloadFilesTask().execute(url1, url2, url3);
When an asynchronous task is executed, the task goes through four steps:
onPreExecute()
doInBackground(Params...)
onProgressUpdate(Progress...)
onPostExecute(Result)
Below is a demo 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 once you created, a task is executed very simply:
new DownloadFilesTask().execute(url1, url2, url3);
Shortest example for just doing something asynchronously:
class MyAsyncTask extends android.os.AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
// Do something asynchronously
return null;
}
}
To run it:
(new MyAsyncTask()).execute();
When you are in the worker thread, you can not directly manipulate UI elements on Android.
When you are using AsyncTask please understand the callback methods.
For example:
public class MyAyncTask extends AsyncTask<Void, Void, Void>{
#Override
protected void onPreExecute() {
// Here you can show progress bar or something on the similar lines.
// Since you are in a UI thread here.
super.onPreExecute();
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
// After completing execution of given task, control will return here.
// Hence if you want to populate UI elements with fetched data, do it here.
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
// You can track you progress update here
}
#Override
protected Void doInBackground(Void... params) {
// Here you are in the worker thread and you are not allowed to access UI thread from here.
// Here you can perform network operations or any heavy operations you want.
return null;
}
}
FYI:
To access the UI thread from a worker thread, you either use runOnUiThread() method or post method on your view.
For instance:
runOnUiThread(new Runnable() {
textView.setText("something.");
});
or
yourview.post(new Runnable() {
yourview.setText("something");
});
This will help you know the things better. Hence in you case, you need to set your textview in the onPostExecute() method.
I would recommend making your life easier by using this library for background works:
https://github.com/Arasthel/AsyncJobLibrary
It's this simple...
AsyncJob.doInBackground(new AsyncJob.OnBackgroundJob() {
#Override
public void doOnBackground() {
startRecording();
}
});
Sample Async Task with POST request:
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("key1", "value1"));
params.add(new BasicNameValuePair("key1", "value2"));
new WEBSERVICEREQUESTOR(URL, params).execute();
class WEBSERVICEREQUESTOR extends AsyncTask<String, Integer, String>
{
String URL;
List<NameValuePair> parameters;
private ProgressDialog pDialog;
public WEBSERVICEREQUESTOR(String url, List<NameValuePair> params)
{
this.URL = url;
this.parameters = params;
}
#Override
protected void onPreExecute()
{
pDialog = new ProgressDialog(LoginActivity.this);
pDialog.setMessage("Processing Request...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
super.onPreExecute();
}
#Override
protected String doInBackground(String... params)
{
try
{
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpEntity httpEntity = null;
HttpResponse httpResponse = null;
HttpPost httpPost = new HttpPost(URL);
if (parameters != null)
{
httpPost.setEntity(new UrlEncodedFormEntity(parameters));
}
httpResponse = httpClient.execute(httpPost);
httpEntity = httpResponse.getEntity();
return EntityUtils.toString(httpEntity);
} catch (Exception e)
{
}
return "";
}
#Override
protected void onPostExecute(String result)
{
pDialog.dismiss();
try
{
}
catch (Exception e)
{
}
super.onPostExecute(result);
}
}
Update: March 2020
According to Android developer official documentation, AsyncTask is now deprecated.
It's recommended to use kotlin corourines instead. Simply, it allows you to write asynchronous tasks in a sequential style.
Simply:
LongOperation MyTask = new LongOperation();
MyTask.execute();
You need to declare the button onclicklistener. Once clicked, it calls AsyncTask class DownloadJson.
The process will be shown below:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new DownloadJson().execute();
}
});
}
// DownloadJSON AsyncTask
private class DownloadJson extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
newlist = new ArrayList<HashMap<String, String>>();
json = jsonParser.makeHttpRequest(json, "POST");
try {
newarray = new JSONArray(json);
for (int i = 0; i < countdisplay; i++) {
HashMap<String, String> eachnew = new HashMap<String, String>();
newobject = newarray.getJSONObject(i);
eachnew.put("id", newobject.getString("ID"));
eachnew.put("name", newobject.getString("Name"));
newlist.add(eachnew);
}
}
} catch (JSONException e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void args) {
newlisttemp.addAll(newlist);
NewAdapterpager newadapterpager = new NewAdapterpager(ProcesssActivitypager.this, newlisttemp);
newpager.setAdapter(newadapterpager);
}
}
private class AsyncTaskDemo extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Showing progress dialog
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Loading...");
progressDialog.setCancelable(false);
progressDialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
// Do code here
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// Dismiss the progress dialog
if (progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
#Override
protected void onCancelled() {
super.onCancelled();
progressDialog.dismiss();
Toast toast = Toast.makeText(
getActivity(),
"An error is occurred due to some problem",
Toast.LENGTH_LONG);
toast.setGravity(Gravity.TOP, 25, 400);
toast.show();
}
}
While working with AsyncTask, it is necessary to create a class-successor and in it to register the implementation of methods necessary for us. In this lesson we will look at three methods:
doInBackground - will be executed in a new thread, and here we solve all our difficult tasks. Because a non-primary thread does not have access to the UI.
onPreExecute - executed before doInBackground and has access to the UI
onPostExecute - executed after doInBackground (does not work if AsyncTask was canceled - about this in the next lessons) and has access to the UI.
This is the MyAsyncTask class:
class MyAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
tvInfo.setText("Start");
}
#Override
protected Void doInBackground(Void... params) {
// Your background method
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
tvInfo.setText("Finish");
}
}
And this is how to call in your Activity or Fragment:
MyAsyncTask myAsyncTask = new MyAsyncTask();
myAsyncTask.execute();
AsyncTask:
public class MainActivity extends AppCompatActivity {
private String ApiUrl="your_api";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyTask myTask=new MyTask();
try {
String result=myTask.execute(ApiUrl).get();
Toast.makeText(getApplicationContext(),result,Toast.LENGTH_SHORT).show();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public class MyTask extends AsyncTask<String,Void,String>{
#Override
protected String doInBackground(String... strings) {
String result="";
HttpURLConnection httpURLConnection=null;
URL url;
try {
url=new URL(strings[0]);
httpURLConnection=(HttpURLConnection) url.openConnection();
InputStream inputStream=httpURLConnection.getInputStream();
InputStreamReader reader=new InputStreamReader(inputStream);
result=getData(reader);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
public String getData(InputStreamReader reader) throws IOException{
String result="";
int data=reader.read();
while (data!=-1){
char now=(char) data;
result+=data;
data=reader.read();
}
return result;
}
}
}
Sample AsyncTask example with progress
import android.animation.ObjectAnimator;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
public class AsyncTaskActivity extends AppCompatActivity implements View.OnClickListener {
Button btn;
ProgressBar progressBar;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(this);
progressBar = (ProgressBar)findViewById(R.id.pbar);
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.button1:
new LongOperation().execute("");
break;
}
}
private class LongOperation extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... params) {
Log.d("AsyncTask", "doInBackground");
for (int i = 0; i < 5; i++) {
try {
Log.d("AsyncTask", "task "+(i + 1));
publishProgress(i + 1);
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.interrupted();
}
}
return "Completed";
}
#Override
protected void onPostExecute(String result) {
Log.d("AsyncTask", "onPostExecute");
TextView txt = (TextView) findViewById(R.id.output);
txt.setText(result);
progressBar.setProgress(0);
}
#Override
protected void onPreExecute() {
Log.d("AsyncTask", "onPreExecute");
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("onPreExecute");
progressBar.setMax(500);
progressBar.setProgress(0);
}
#Override
protected void onProgressUpdate(Integer... values) {
Log.d("AsyncTask", "onProgressUpdate "+values[0]);
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("onProgressUpdate "+values[0]);
ObjectAnimator animation = ObjectAnimator.ofInt(progressBar, "progress", 100 * values[0]);
animation.setDuration(1000);
animation.setInterpolator(new LinearInterpolator());
animation.start();
}
}
}
if you open AsyncTask class you can see below code.
public abstract class AsyncTask<Params, Progress, Result> {
#WorkerThread
protected abstract Result doInBackground(Params... params);
#MainThread
protected void onPreExecute() {
}
#SuppressWarnings({"UnusedDeclaration"})
#MainThread
protected void onPostExecute(Result result) {
}
}
AsyncTask features
AsyncTask is abstract class
AsyncTask is have 3 generic params.
AsyncTask has abstract method of doInBackground, onPreExecute, onPostExecute
doInBackground is WorkerThread (you can't update UI)
onPreExecute is MainThread
onPostExecute is MainThread (you can update UI)
example
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
mEmailView = (AutoCompleteTextView) findViewById(R.id.email);
AsyncTask<Void, Void, Post> asyncTask = new AsyncTask<Void, Void, Post>() {
#Override
protected Post doInBackground(Void... params) {
try {
ApiClient defaultClient = Configuration.getDefaultApiClient();
String authorization = "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1ODIxMzM4MTB9.bA3Byc_SuB6jzqUGAY4Pyt4oBNg0VfDRctZ8-PcPlYg"; // String | JWT token for Authorization
ApiKeyAuth Bearer = (ApiKeyAuth) defaultClient.getAuthentication("Bearer");
Bearer.setApiKey(authorization);
PostApi apiInstance = new PostApi();
String id = "1"; // String | id
Integer commentPage = 1; // Integer | Page number for Comment
Integer commentPer = 10; // Integer | Per page number For Comment
Post result;
try {
result = apiInstance.apiV1PostsIdGet(id, authorization, commentPage, commentPer);
} catch (ApiException e) {
e.printStackTrace();
result = new Post();
}
return result;
} catch (Exception e) {
e.printStackTrace();
return new Post();
}
}
#Override
protected void onPostExecute(Post post) {
super.onPostExecute(post);
if (post != null) {
mEmailView.setText(post.getBody());
System.out.print(post);
}
}
};
asyncTask.execute();
}
Change your code as given below:
#Override
protected void onPostExecute(String result) {
runOnUiThread(new Runnable() {
public void run() {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");
}
});
}