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"
}
}
Related
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 trying to send a string from one class to another using AsyncTask. In the code below everything is working with no errors, but I am wanting to get the returned str from newThread.execute() and save it to the string test. I have tried test = newThread.execute(), but I that produces the following error: Type mismatch: cannot convert from AsyncTask to String.
Class1.java
public void changText(View view) {
String test = "";
NewThread newThread = new NewThread();
newThread.execute();
}
Class2.java
public class NewThread extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... params) {
String str = "this is a test";
return str;
}
Any help would be greatly appreciated.
AsyncTask doesn't work like that, AsyncTask must be subclassed to be used.
the propose of an AsyncTask is execute some code in a separate thread (different from UI thread), but the result from that code, when ready, will be delivered in onPostExecute.
So, your code will look like this:
public Class1{
String test = "";
public void changText(View view) {
NewThread newThread = new NewThread();
newThread.execute("input");
}
public class NewThread extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
String str = params[0] + " this is a test";
return str;
}
#Override
protected void onPostExecute(String result) {
test = result;
}
}
}
You need a way to publish the result via some callback mechanism if you put an AsyncTask into it's own file. According to the dependency inversion principle it's better to let the AsyncTask define the callback mechanism instead of making it depend on some activity directly.
The resulting task could then look like this:
public class NewThread extends AsyncTask<String, Integer, String> {
/** A callback interface to be implemented by clients of this class */
public interface NewThreadClient {
void onNewThreadResult(String result);
}
private final NewThreadClient mClient;
public NewThread(NewThreadClient client) {
mClient = client;
}
#Override
protected String doInBackground(String... params) {
String str = "this is a test";
return str;
}
#Override
protected void onPostExecute(String result) {
mClient.onNewThreadResult(result);
}
}
To use it you'll need something that implements the callback. For example an Activity
public class TestActivity extends Activity implements NewThread.NewThreadClient {
private TextView mText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// simple textview actually intended for listviews..
setContentView(android.R.layout.simple_list_item_1);
mText = (TextView) findViewById(android.R.id.text1);
new NewThread(this).execute();
}
#Override
public void onNewThreadResult(String result) {
mText.setText(result);
}
}
The point of AsyncTask is that it does things asynchronously (while your program does other things, the result will be calculated at some point in the future). You can not (there are ways but it makes absolutely no sense) get the result immediately. test = newThread.execute() would require that the result is immediately available. If you start to wait for the result you would block any progress that could happen in the meantime.
Callbacks are the most common way to get a result at a later point in time. AsyncTask has onPostExecute built-in for that purpose (also to deliver the result within the UI thread) and you can use it directly if you make your AsyncTasks an inner class. Add another layer of callbacks and you can easily use them across classes.
See if you intend to do what i have done in following code
package com.example.myfirstapp;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
public class MyActivity extends Activity {
private String test;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
NewThread newThread = new NewThread();
newThread.execute();
}
class NewThread extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... params) {
String str = "this is a test";
return str;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
test=result;
// update the UI like view.setText(test);
}
}
}
Try this:
String test = newThread.execute().get();
The value returned from newThread.execute() is not the results of the computation; it's the AsyncTask itself. To publish your results, write a method in NewThread :
void onPostExecute(ArrayList<HashMap<String,String>> result) {
returnString = result; // or something similar
// then update the UI to reflect the results
}
As in Doc AsyncTask. execute (Params... params)
Return instance of AsyncTask.
but you are trying to assign AsyncTask instance to String. to get result back from Asynctask as String you should call execute().get() method on main thread as:
NewThread newThread = new NewThread();
String test= newThread.execute().get(); //<< get String from doInBackground
but this will stop execution of main thread until doInBackground method execution not completed.
if you want to get result from doInBackground without stopping execution of main thread then use onPostExecute for updating UI because this method called on Main UI Thread when doInBackground execution complete :
#Override
protected void onPostExecute(String result) {
test = result; //<< get result here
}
I've got an Activity where before showing the Text/EditText fields, I want to make a call to the server to get the details and then setText of the fields based on the data gotten back from the server.
Below is what I'm doing but the fields don't seem to have the data fetched from the server. I think because I am calling an AsyncTask which gets run in the background and in the mean time the fields are shown to the user.
Question
How does android deal with this? What pattern should I be using?
This activity gets called from MainActivity.java like so:
Intent act = new Intent(getApplicationContext(), MySecondActivity.class);
create.putExtra("theId", "138");
startActivity(create);
in MySecondActivity.java i do the following:
public class MySecondActivity extends SherlockActivity {
private EditText fieldOne;
private EditText fieldTwo;
private MyObj obj = new MyObj();
private int id;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.shared_activity);
fieldOne = (EditText)findViewById(R.id.field_one);
fieldTwo = (EditText)findViewById(R.id.field_two);
id = Integer.parseInt(getIntent().getStringExtra("theId"));
new FetchDetail().execute();
//If I put the below two lines inside the AsyncTask then I get an error:
//"Only the original thread that created a view hierarchy can touch its views."
fieldOne.setText(obj.getOne()); //
fieldTwo.setText(obj.getTwo()); //
}
class FetchDetail extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... strings) {
final RestAdapter restAdapter = new
RestAdapter.Builder().setServer("http://10.0.2.2:8080").build();
final MyTaskService apiManager = restAdapter.create(MyTaskService.class);
final MyObj obj = apiManager.getDetails(id);
return null;
}
}
}
If I put the below two lines inside the AsyncTask then I get an error
Have these in onPostExcute
fieldOne.setText(obj.getOne());
fieldTwo.setText(obj.getTwo());
Do your background computation in doInbackground. Return result in doInbackground. The result of doInbackground computation is a pram to onPostExecute.
So you can update ui in onPostExecute which is invoked on the ui thread
Example:
protected String doInBackground(String... params)
{
// background computation
return "hello"; // return string
}
#Override
protected void onPostExecute(String result) // string
{
super.onPostExecute(result);
fieldOne.setText(result); // hello is set to field One
}
For more info read the topic under The4Steps in the docs
http://developer.android.com/reference/android/os/AsyncTask.html
AsyncTask has 3 methods to override:
1: onPreExecute
Executes on UI thread. So do what you want to do on UI before service call here(Ex: show a progress dialog).
2: doInBackground
Executes in background so perform long running task like fetching data from server.
3: onPostExecute
Executes on UI thread and gets called once doInBackground is completed you can process the result here and update the UI
Ex:
public class RestServiceTask extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
}
#Override
protected void onPostExecute(String result) {
}
}
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
Dear Android hackers,
I am trying to do the following in my Android App: When the User clicks on a list item in a ListActivity, a ProgressDialog should show up, some preloading should happen and after it's done, another Activity should be called using an intent.
I tried different approaches. What didn't work at all was using an Async Task. Apparently I cannot show, dismiss or edit my ProgressDialog out of the Async Task, if that Class is not a Member of my original Activity.
I switched to a simple Thread then, this is how I'm trying to do it:
dialog = ProgressDialog.show(BookmarkActivity.this, "", "Loading...",true);
new Thread() {
public void run() {
// do something
dialog.setMessage("Change Message...");
// do more
dialog.dismiss();
// ...
Intent intent = new Intent(BookmarkActivity.this, ThreadActivity.class);
BookmarkActivity.this.startActivity(intent);
}
}.start();
This works almost, but the changing of the dialog message does not. I'm getting errors saying something about "leaked windows". (I can post the complete log if it is needed).
My questions:
How can I use an Async Task for this, where the Class has it's own file?
How can I change the ProgressDialog out of my Thread or AsyncTask without causing an error for changing the UI in another thread?
Thanks in advance, Jan Oliver
Ok, with the help of Jason, I put together this Async Task. That works!
public class ThreadPreLoader extends AsyncTask<Object, String, Void> {
private Activity mActivity;
private ProgressDialog mDialog;
public ThreadPreLoader(Activity activity) {
mActivity = activity;
}
protected void onPreExecute() {
mDialog = new ProgressDialog(mActivity);
mDialog.setMessage("Loading...");
mDialog.show();
}
protected Void doInBackground(Object... args) {
publishProgress("Loading something else..");
return null;
}
protected void onProgressUpdate(String... msg) {
mDialog.setMessage(msg[0]);
}
protected void onPostExecute(Void result) {
mDialog.dismiss();
}
}
Thanks again, Jason.
You should use an Async Task, Define a custom Async Task which receives the context (this) of the original activity.
Then keep that context for later Dismissing the dialog.
From your doInBackground() method you can call postProgress( int progress) which will cause onProgressUpdate() to be called in the async task , this method is on the UI thread so it will not cause cross thread errors.
Once doInBackground() is complete the method onComplete() will also be called on the UI thread, this is where you can use your saved context and dissmiss the dialog (context.dissmissDialog()
Take a look at Android's Handler class. If you create the Handler in the onCreate method of your activity, Runnables that are sent to the post method of the handler are then run on the UI thread of your activity:
Handler h;
protected void onCreate(Bundle bundle) {
h = new Handler;
new Thread() {
public void run() {
// your run code
h.post(new Runnable() { /* change dialog here */ });
}
}.start();
}
I'm not sure that's the best option, but worth a try.
In AsyncTask
You should do you work which need time in doInBackground and calling intent like things, that you need to do after this task should be in onPostExecute
public class ThreadPreLoader extends AsyncTask<Object, String, Void> {
private Activity mActivity;
private ProgressDialog mDialog;
public ThreadPreLoader(Activity activity) {
mActivity = activity;
}
protected void onPreExecute() {
mDialog = new ProgressDialog(mActivity);
mDialog.setMessage("Loading...");
mDialog.show();
}
protected Void doInBackground(Object... args) {
//do more
publishProgress("Loading something and reached somewhere..");
//do more
publishProgress("Loading something and reached somewhere..");
//do more
return null;
}
protected void onProgressUpdate(String msg) {
mDialog.setMessage(msg);
}
protected void onPostExecute() {
Intent intent = new Intent(BookmarkActivity.this, ThreadActivity.class);
BookmarkActivity.this.startActivity(intent);
mDialog.dismiss();
}
}