Inner Class Can Access But Not Update Values - Asynctask

Inner class can access but not update values - AsyncTask

How can I ensure that the values remain updated?

They will be updated since they are member variables. However, since AsyncTask is asynchrounous, they might not be updated yet when you check them. You can use an interface to create a callback when these values are updated. This SO answer covers how to do this

Does that mean that any values updated in the new thread will be lost once that thread returns?

No they shouldn't be "lost". They probably just haven't been changed in the AsyncTask when you check them.

Since this isn't your actual code I can't see when you are trying to access them but you can use the interface method or call the functions that need these values in onPostExecute(). You also can do a null check before trying to access them. It just depends on the functionality and flow that you need as to which is the best way. Hope that helps.

Edit

In the answer I linked to, you tell the Activity that you will use that interface and override its method(s) with implements AsyncResponse in your Activity declaration after creating the separate interface class

public class MainActivity implements AsyncResponse{

then, in your Activity still, you override the method you declared in that class (void processFinish(String output);)

@Override
void processFinish(String output){ // using same params as onPostExecute()
//this you will received result fired from async class of onPostExecute(result) method.
}

then this is called in onPostExecute() when the listener sees that it is done with delegate.processFinish(result); delegate is an instance of AsyncResponse (your interface class)

    public class AasyncTask extends AsyncTask{
public AsyncResponse delegate=null;

@Override
protected void onPostExecute(String result) {
delegate.processFinish(result);
}

Interface example taken from linked answer above and adjusted/commented for clarity. So be sure to upvote that answer if it helps anyone.

Asynctask inner class not updating UI textview

You have not called ASyncTask, execute it like this after initializing TextView:

txtview = (TextView) findViewById(R.id.mainview);
SimpleTask objSimpleTask=new SimpleTask();
objSimpleTask.execute();

Hope is what you want.

doInBackground not updating variable

The problem is that your AsyncTask is executed asynchronously, while you try to retrieve the value immediately. You need to implement this a little bit differently. Either leverage the API of AsyncTask, sine it posts callbacks for your on the UI thread. You can update your TextView directly in your AsyncTask

class MyAwesomeAsyncTask extends AsyncTask<Void, Void, String> {

@Override
protected void onPreExecute() {
myTextView.setText("progress started");
}

@Override
protected String doInBackground(final Void... voids) {
String s = amazingCallToBackend();
return s;
}

@Override
protected void onPostExecute(final String s) {
myTextView.setText(s);
}
}

Or if you just want the value, you can pass a Callback to your async task that will deliver the value to you, something like that

interface Callback {
void onValueReceived(String value);
void onFailure();
}

class MyAwesomeAsyncTask extends AsyncTask<Void, Void, String> {

private Callback callback;

MyAwesomeAsyncTask(final Callback callback) {
this.callback = callback;
}

@Override
protected String doInBackground(final Void... voids) {
String s = amazingCallToBackend();
return s;
}

@Override
protected void onPostExecute(final String s) {
callback.onValueReceived(s);
}
}

Here's how you create it

Callback callback = new Callback() {
@Override
public void onValueReceived(final String value) {

}

@Override
public void onFailure() {

}
};

new MyAwesomeAsyncTask(callback).execute();

However, be careful because if for some reason your activity/fragment is gone/finished before your AsyncTask is done, this can cause memory leaks.

A quick Google search will tell you all you want about AsyncTask leaking memory :)

What's the correct way to implement AsyncTask? static or non static nested class?

In general I would recommend the static implementation (though both are acceptable).

The Google approach will require less code but your asynctask will be tightly coupled with your actitivy (which means not easily reusable). But sometimes this approach is more readable.

With the CommonsGuy approach, it will require more effort (and more code) to decouple activity and asynctask, but in the end you will have a more modular, more reusable code.

Access private variable from inner class (AsyncTask)

The entire point of an async task is that it is asynchronous. If you execute a task, you will not get the results back on your next line of code. In order to evaluate the result, you should be using the onPostExecute callback method.

@Override
protected void onPostExecute(String s) {
if(sentResult==true){
Toast toast = Toast.makeText(this.context, "Message Sent", Toast.LENGTH_LONG);
toast.show();
}else{
Toast toast = Toast.makeText(this.context, "ERROR: Message not Sent", Toast.LENGTH_LONG);
toast.show();
}
}

Also, if you were to change your method signatures, you wouldn't even need an external variable.

private class SenderAsync extends AsyncTask<String,String,Boolean> {

@Override
protected void onPostExecute(Boolean sent) {
if(sent == true){
Toast toast = Toast.makeText(this.context, "Message Sent", Toast.LENGTH_LONG);
toast.show();
}else{
Toast toast = Toast.makeText(this.context, "ERROR: Message not Sent", Toast.LENGTH_LONG);
toast.show();
}
}

@Override
protected Boolean doInBackground(String... params) {
try {
...
if (resp.getStatusLine().getStatusCode() == 200) {
return true;
}
}
catch (IOException e) {

}

return false;
}

updating UI thread while in asynctask

This line here

TextView tv = (TextView) findViewById(R.id.thingsThatNeedToBeUpdated);

is obviously declared either

  1. Outside of a method -which would result in tv being null or
  2. In a method that isn't part of the AsyncTask- which would mean the
    task doesn't have access to it

You should define it as a member variable (outside of a method)

TextView tv;

then initialize it inside of a method

tv = (TextView) findViewById(R.id.thingsThatNeedToBeUpdated);

This will give your task access to it as well as the rest of your class.

If your AsyncTask is a separate file than your Activity then you will want to see this answer on using an interface and create a callback to update the TextView in your Activity.

AsyncTask as Inner class and static field issue

I have understand where is the problem.
You have to run the search method on the UI thread.

So change this code block:

  @Override  
protected Void doInBackground(String... strings) {
try {

search(strings[0], string[1]);
return null;

} catch(Exception e) {
}

}

with this

 @Override  
protected Void doInBackground(final String... strings) {
try {
runOnUiThread(new Runnable() {
public void run() {
search(strings[0], string[1]);
return null;
}
});

} catch(Exception e) {
e.printStackTrace();
}
}

And all should works correctly.

Android AsyncTask as NOT an Inner class : Weird NullPointerException

As Pedro stated in his comment you don't want to try and instantiate an Activity the way you are.

All you need to do is to pass the value from the first to second Activity. Then you can pass that value to the constructor of your AsyncTask.

So, in your onClick() of the first Activity you pass it as an Extra.

public void StartSecondActivity(View v) {
Intent intent = new Intent(this, SecondActivity.class);
EditText et = (EditText) findViewById(R.id.mainActivity_editText1);
String temp = et.getText().toString();
intent.putExtra("temp", temp);
startActivity(intent);
}

then retrieve it and pass it to the task

public class SecondActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// get the String
Intent i = getIntent();
String temp = i.getStringExtra("temp");
setContentView(R.layout.activity_second);

// and pass it here
new MyTask(temp).execute();
}
}

now get it in your task

MyTask(String value) {
searchString= value;
}

Android: How to update an UI from AsyncTask if AsyncTask is in a separate class?

AsyncTask is always separate class from Activity, but I suspect you mean it is in different file than your activity class file, so you cannot benefit from being activity's inner class. Simply pass Activity context as argument to your Async Task (i.e. to its constructor)

class MyAsyncTask extends AsyncTask<URL, Integer, Long> {

WeakReference<Activity> mWeakActivity;

public MyAsyncTask(Activity activity) {
mWeakActivity = new WeakReference<Activity>(activity);
}

...

and use when you need it (remember to NOT use in during doInBackground()) i.e. so when you would normally call

int id = findViewById(...)

in AsyncTask you call i.e.

Activity activity = mWeakActivity.get();
if (activity != null) {
int id = activity.findViewById(...);
}

Note that our Activity can be gone while doInBackground() is in progress (so the reference returned can become null), but by using WeakReference we do not prevent GC from collecting it (and leaking memory) and as Activity is gone, it's usually pointless to even try to update it state (still, depending on your logic you may want to do something like changing internal state or update DB, but touching UI must be skipped).



Related Topics



Leave a reply



Submit