i cant take my value in asynctask on android - java

String[] a = new String[2];
String[] b = new String[2];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
new AsyncTaskClass().execute();
// in here when i use a it gets me a but i write a = b in method().
}
class AsyncTaskClass extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
}
#Override
protected String doInBackground(String... strings) {
method();
return null;
}
#Override
protected void onPostExecute(String s) {
}
}
void method() {
a = b;
}
method() is working i put a toast messg in it and i saw the mssg,but it doesnt work(a=b)
by the way a and b is defined.we call that a={"a","b"}; b={"c","d"}; when i use a[0] code gets me "a". why? this is the question

doInBackground is being executed in background thread, so once you call .execute(), execution will pass your:
//in here when i use a it gets me a but i write a = b in method().
line, and your doInBackground will certainly not yet execute (but it might), you should move all your processing to onPostExecute if it depends on doInBackground results.

Related

AsyncTask - How to pass value back to activity class after onPostExecute?

Here is my problem. I have created a asyncTask to link to my database and send and receive information using JSON.
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
progressDialog.dismiss();
returnValues = dataParsed.split("\\s+");
mainActivity.getValue(this is the function that calls anotherfunction in
asyncTask)
Log.v("ARRAY LENGTH", String.valueOf(returnValues.length));
}
public String[] returnmyString(){
//return mySaveData;
Log.v("ARRAY LENGTH 2", String.valueOf(returnValues.length));
return returnValues;
}
I create the asyncTask object within my activity based class and then call that object.execute. My problem is that my code will continue to run once calling the object.execute and one of the lines calls a function within the asyncTask class before it is done executing all the code.
process.activitySave(1); //<---Process is the object for the asyncTask class
process.ContextSave(this,ServerURLSource,myParameters);
process.execute()
changedData = process.returnmyString(); //<-- this is the line of code that gets implemented that returns a null value
I have tried creating a Mainactivity object in the asyncTask class and then calling a function then that retrieves the value but my app crashes when I do this. any help would be appreciated. I would like to put some sort of listener in the mainactivity class as it seems I cannot reference any of the functions from my mainactivity class in my asyncTask class.
This is the function within the asyncTask to return the value:
public String[] returnmyString(){
//return mySaveData;
Log.v("ARRAY LENGTH", String.valueOf(returnValues.length));
return returnValues;
}
Method 1 is the basic, anonymous inner class implementation. Because of the inner AsyncTask class is not static class, you can access to the CustomActivity's properties from that implementation.
In Method 2, AsyncClass implemented separately. If you gave your activity to this class, it can be call back your desired method after execution. This method, for our example is the #setChangedData method. CustomAsyncTask call backs the #setChangedData in the #onPostExecute.
public class CustomActivity extends AppCompatActivity {
String mChangedData;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Method 1 - change data into the anonymously implemented AsyncTask class
new AsyncTask<Integer, Void, Void>() {
#Override
protected Void doInBackground(Integer... params) {
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
CustomActivity.this.mChangedData = "foo"; // this changes mChangedData as "foo"
}
}.execute(1);
// Method 2 - change data into the custom AsyncTask class
new CustomAsyncTask(this).execute(2);
}
public void setChangedData(String changedData){
this.mChangedData = changedData;
}
static class CustomAsyncTask extends AsyncTask<Integer, Void, Void> {
CustomActivity mActivity;
public CustomAsyncTask(CustomActivity activity) {
this.mActivity = activity;
}
#Override
protected Void doInBackground(Integer... params) {
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
mActivity.setChangedData("bar");
}
}
}
And, as method 3, if you want to separate you Activity and AsyncTask more loosely, this is the handler method:
public class CustomActivity extends AppCompatActivity {
private String mChangedData;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CustomAsyncTask task = new CustomAsyncTask();
task.setOnDataChangedListener(new CustomAsyncTask.OnDataChangedListener() {
#Override
public void onDataChanged(String data) {
mChangedData = data;
}
});
task.execute(1);
}
private static class CustomAsyncTask extends AsyncTask<Integer, Void, Void> {
private OnDataChangedListener onDataChangedListener;
#Override
protected Void doInBackground(Integer... params) {
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if(onDataChangedListener != null) {
onDataChangedListener.onDataChanged("foo");
}
}
void setOnDataChangedListener(OnDataChangedListener onDataChangedListener) {
this.onDataChangedListener = onDataChangedListener;
}
interface OnDataChangedListener {
void onDataChanged(String data);
}
}
}

Android: toast inside AsyncTask

I have an AsyncTask class SearchForQuestions that is called from an Activity QuizMap. When looping through an array in SearchForQuestions I can't find the correct context for toast to appear within the AsynTask.
The standard Toast.makeText(getApplicationContext(), "This is Toast!!!", Toast.LENGTH_SHORT).show(); gives error getApplicationContext() undefined.
I have tried some of the solutions to this offerred by SO, most of them are listed here and concern getting UiThread and running on that.
I can't get this to work however. Here's example code snippets of what i have tried. I have put a method in QuizMap and try calling it from SearchForQuestions but SearchForQuestions isn't recognised. How can I get around this? )Still a newbie at java...)
// QuizMap activity
public class QuizMap extends FragmentActivity
implements OnMarkerClickListener {
private GoogleMap map;
private static final String TAG = "QuizMap"; // debugging
...
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_quizmap);
map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
.getMap();
...
}
// make toast inside AsyncTask
public void showNotNearToast(final String toast) {
QuizMap.this.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(QuizMap.this, "This is Toast!!!", Toast.LENGTH_SHORT).show();
}});
}
.
// SearchForQuestions class
private class SearchForQuestions extends AsyncTask<String, Void, DataHandler> {
// checks for proximity to question locations
Location location =
locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
#Override
protected DataHandler doInBackground(String... pointsList) {
String result = pointsList[0];
...
}
#Override
protected void onPostExecute(DataHandler result) {
ArrayList<String> resultsArray = result.results;
Integer numPoints = resultsArray.size();
for (int i =0;i<numPoints;i++){
String[] pointDetails = resultsArray.get(i).split("::");
...
// we can make use of the Android distanceTo function to calculate the distances
float distance = location.distanceTo(fixedLoc);
if (i > DIST) { // this is UCL
showNotNearToast("My Message"); // showNotNearToast undefined
if (distance < DIST) {
...
}
};
I'm going t close this question. I haven't solved my problem but the number of answers provided that apparently work in other situations suggest there's something else going on. I'm going to re-structure the classes to get around having to call from within AsyncTask.
Just Toast it, why do you want to create a function for it? onPostExecute() is already on UI thread.
You are not able to access because inner Class can not call functions of Outer class unless you pass instance of the outer class.
Call your toast in onPostExecute
Create an interface for a callback.
public interface ToastCallback {
public void invoke(String text);
}
Your AsyncTask constructor
private ToastCallback toastCallback;
public SearchQuestions(ToastCallback callback) {
this.toastCallback = callback;
}
// in doInBackground() {
toastCallback.invoke("Toast from background");
}
In Your Activity,
private void showNotNearToast(String text) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}
});
}
public class MyToastCallback implements ToastCallback {
#Override
public void invoke(String text) {
showNotNearToast(text);
}
}
// Asynctask call
new SearchQuestion(new MyTosatCallback()).execute(<Your params here>);
Try this from inside your AsyncTask:
myActivity.this.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show();
}
});
Where you have your
showNotNearToast("My Message"); // showNotNearToast undefined
Replace myActivity with the name of your Activity.
(Ab)use the publishProgress method
private class ToastAsyncTask extends AsyncTask<Void, String, Void>{
#Override
protected Void doInBackground(Void... voids) {
SystemClock.sleep(1000);
publishProgress("Toast msg string");
SystemClock.sleep(1000);
return null;
}
#Override
protected void onProgressUpdate(String... values) {
Toast.makeText(getApplicationContext(), values[0], Toast.LENGTH_SHORT).show();
}
}
**UPDATE: ** since you are having problems with context for some reason, use this version. Tough the implementation above works for me.
private class ToastAsyncTask extends AsyncTask<Void, String, Void> {
private WeakReference<Context> contextRef;
public ToastAsyncTask(Context context) {
contextRef = new WeakReference<Context>(context);
}
#Override
protected Void doInBackground(Void... voids) {
SystemClock.sleep(1000);
publishProgress("Toast msg string");
SystemClock.sleep(1000);
return null;
}
#Override
protected void onProgressUpdate(String... values) {
if (contextRef.get() != null) {
Toast.makeText(contextRef.get(), values[0], Toast.LENGTH_SHORT).show();
} else {
// The context was destroyed.. check what you are doing
}
}
}
Use it like this
new ToastAsyncTask(MainActivity.this).execute();
Pass the activity into the AsyncTask. See below.
private class SearchForQuestions extends AsyncTask<String, Void, DataHandler> {
Activity activity;
public void SearchForQuestions(Activity activity){
this.activity = activity;
}
//... rest of the code
public class QuizMap extends FragmentActivity implements OnMarkerClickListener {
/*...*/
new SearchForQuestions(this).execute();
/*...*/
/*When calling the toast:*/
Toast.makeText(this.activity, "This is Toast!!!", Toast.LENGTH_SHORT).show();

How Can I Send Value From onPostExecute() to Activity

First of all I must say I'am new at Android but not at Java.
I did HttpRequest With AsyncTask.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Thread th = new Thread(new Runnable() {
#Override
public void run() {
new RequestTask().execute("http://www.url.com/ajaxrequest/?kategori=27");
}
});
th.start();
}
Created Another Class ( Name : RequesTask )
class RequestTask extends AsyncTask<String, String, String>{
private void RequestTask(String URL){
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response;
// Some Codes Here...
return responseString;
}
#Override
protected String doInBackground(String... uri) {
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response;
String responseString = null;
// Some Codes Here...
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// My Result is 'result'
}
I want to send and write this string value to TextView In MainActivty. How can i send 'result' ?
Thanks in advance..
Don't open a new thread to run the async task from this thread. It won't work (will fail on internal handler). The async task by himself open for you a new thread.
This is the right code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.your_text_view);
new RequestTask().execute("http://www.url.com/ajaxrequest/?kategori=27");
}
And in your RequestTask
#Override
protected void onPostExecute(String result) {
textView.setText(result);
}
Edit: To your question, how to access TextView from AsyncTask
You can do it in many ways. These are part of them:
Define AyncTask as an inner class inside your Activity. You can access members of Activity within AsyncTask. This option is very coupled, means async task which apparently the logic of your app is part of your ui. Like this:
class YouActivity extends Activity {
TextView textView;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.your_text_view);
new RequestTask().execute("http://www.url.com/ajaxrequest/?kategori=27");
}
class RequestTask extends AsyncTask<String, String, String> {
...
#Override
protected void onPostExecute(String result) {
textView.setText(result);
}
}
}
Deliver the TextView to AsyncTask by constructor or setter method. This option is less coupled, since this AsyncTask can be used by many consumers who want to update their TextView, but the is still coupling by holding reference from AsyncTask to your views.
Your AsyncTask:
class RequestTask extends AsyncTask<String, String, String> {
TextView textView = null;
public void setTextView(TextView textView) {
this.textView = textView;
}
...
#Override
protected void onPostExecute(String result) {
if (textView != null) {
textView.setText(result);
}
}
}
And your activity:
class YouActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = (TextView) findViewById(R.id.your_text_view);
RequestTask requestTask = new RequestTask();
requestTask.setTextView(textView);
requestTask.execute("http://www.url.com/ajaxrequest/?kategori=27");
}
}
To make your program more loosely coupled and to make better separation of controller from your views, use Handlers:
class RequestTask extends AsyncTask<String, String, String> {
Handler handler = null;
public void setHandler(Handler handler) {
this.handler = handler;
}
...
#Override
protected void onPostExecute(String result) {
if (handler != null) {
Message message = new Message();
message.obj = result;
handler.sendMessage(message);
}
}
}
And your activity:
class YouActivity extends Activity {
TextView textView;
Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
String value = (String) msg.obj;
textView.setText(value);
}
};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.your_text_view);
RequestTask requestTask = new RequestTask();
requestTask.setHandler(handler);
requestTask.execute("http://www.url.com/ajaxrequest/?kategori=27");
}
}
Handlers cave tons of options. You can 'send message' from any thread and you can decouple your app very good with this tool.
You can either pass the TextView to RequestTask's constructor or make it a global member. And in your onPostExecute method:
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
yourTextView.setText(result);
}
That's it :)
Edit: Whoops. As sromku correctly pointed out, AsyncTask already performs the doInBackground() method in a separate thread (in background) so you should not be wrapping it in another thread. So, remove that Thread-ception.
best solution
Instead of using so many classes for different types of asynctask , I suggest you use this library
you can have a look at here
http://loopj.com/android-async-http/
your code will become very very less , instead of declaring so may asynctask seperately writing bulk of code , you can just use 4 lines of code
AsyncHttpClient client = new AsyncHttpClient();
client.get("http://www.google.com", new AsyncHttpResponseHandler() {
#Override
public void onSuccess(String response) {
System.out.println(response);
}
});
I is very efficient in geting the response very quickly.
I hope this will help you out. :)

ensuring an async thread runs on the ui thread

I have objects (not on the ui thread) that need to run the async task as internal methods and I want to pass the ui thread to the method and then implement the ui thread on the asynctask that way - is there a way of doing this?
pseudo-code:
public class EditDetails extends Activity{
MyObject obj = new obj;
obj.syncWithServer(EditDetails.this);
}
public class MyObject {
public void syncWithWerver(EditDetails parent){
final class GetUserHttpTask extends AsyncTask<String/* Param */, Boolean /* Progress */, String /* Result */> {
#Override
protected String doInBackground(String... params) {
return "";
}
#Override
protected String onPostExecute(String result) {
//this doesn't run
}
}
}
}
note: at the moment this isn't working because onPostExecute isn't firing after the doInBackground
EDIT
this code is pseudocode the actual problem is still happening and I have listed it http://pastebin.com/jW6JpUbg here.. basically it gets stuck after running line 72 on the pastebin in never does onPostExecute
Weird enough the onPostExecute should be void. I wonder how is your code compiling as you have changed the return type of overridden method?
After you correct your onPostExecute you can get the AsyncTask run as follows:
final class GetUserHttpTask extends AsyncTask<String/* Param */, Boolean /* Progress */, String /* Result */> {
#Override
protected String doInBackground(String... params) {
return "";
}
#Override
protected String onPostExecute(String result) {
// this will run
}
}
public void syncWithWerver(EditDetails parent){
AsyncTask task = new GetUserHttpTask();
task.execute();
}
Did you tried executing your task like this ?
parent.runOnUiThread(new Runnable() {
#Override
public void run() {
new GetUserHttpTask().execute();
}
});
I think this should work..
Added:
Your AsyncTask implementation should be as below :
Note : Read the updated comments
class GetUserHttpTask extends AsyncTask<String/* in parameter for doInBackground */, Boolean /* in parameter for onProgressUpdate */, String /* Out parameter and in parameter for onPostExecute method*/> {
#Override
protected String doInBackground(String... params) {
return "";
}
#Override
protected void onPostExecute(String result) {
// this doesn't run
}
#Override
protected void onProgressUpdate(Boolean... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
}
}

Async task can't update GUI

My basic question is how do you update the GUI with AsyncTask. I am setting a String in onPostExecute that the GUI thread references. Using logging, I can see the String getting set in the onPostExecute method, but it never gets set on my GUI under my onClickListener to update the GUI. Any help is appreciated.
Main Program:
public class Main extends Activity {
/** Called when the activity is first created. */
Arduino.ToAndroid.Temperature.GetJSON jsonHttpClass = new Arduino.ToAndroid.Temperature.GetJSON();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new GetJSON().execute(url_to_Http);
}
View.OnClickListener temperatureListener = new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
// buttonTemperature = json.getTemp();
tempView.setText(jsonHttpClass.value);
Log.i("ROSS LOG", "Button Clicked");
}
}; }
Async Task:
class GetJSON extends AsyncTask {
public String value;
#Override
protected String doInBackground(String... url) {
String result = this.getHttpJson(url[0]);
return result;
}
#Override
protected void onPostExecute(String result) {
value = new String(result);
Log.i("ROSS LOG", value);
}
}
In onCreate(), you should be using the handle for the already created object of the AsyncTask and not create a new object.
Use
jsonHttpClass.execute(url_to_Http);
instead of
new GetJSON().execute(url_to_Http);

Categories

Resources