how do I return a List generated in an AsyncTask back to the Activity?
My LoadStringsAsync class:
public class LoadStringsAsync extends AsyncTask<Void, Void, List<String> > {
List<String> str;
#Override
protected void onPreExecute() {
super.onPreExecute();
...
}
#Override
protected List<String> doInBackground(Void... arg0) {
...
get content from the internet
and
fill the list
...
}
#Override
protected void onPostExecute(List<String> str) {
super.onPostExecute(events);
...
}
}
and I need the List back in my Activity to work with it. (No not only to show it in ListView :P)
Any suggestions how to do this? :-)
Thanks so far!
your Activity:
public class YourActivity extends Activity {
private List<String> list = new ArrayList<String>();
public void onCreate(Bundle state) {
//...
}
public void setList(List<String> list) {
this.list = list;
}
private void fireYourAsyncTask() {
new LoadStringsAsync(this).execute();
}
}
AsyncTask:
public class LoadStringsAsync extends AsyncTask<Void, Void, List<String>> {
List<String> str;
private YourAcitivity activity;
public LoadStringsAsync(YourAcitivity activity) {
this.activity = activity;
}
#Override
protected List<String> doInBackground(Void... arg0) {
}
#Override
protected void onPostExecute(List<String> str) {
super.onPostExecute(events);
activity.setList(str);
}
}
If you make your AsyncTask an inner class in your Activity, then onPostExecute will be in the same context as the Activity, and you can use the List as you would anywhere in the Activity.
If you don't make your AsyncTask an inner class in your Activity, then you need to set up a listener to call back to your Activity when the AsyncTask finishes. If you prefer to go that route look at this post.
There is also this post that is similar to your question.
According to the documentation from android link you can use the get method to return computational result. Since your AsyncTask shows that you are returning a List, then you can try the following code in the class you are calling the asynchronous class
List<String> returnedlist=new LoadStringAsync().execute().get();
Hoping this option helps.
Place code that uses the list, or sets it to a variable, inside onPostExecute().
Better run your task from parent Activity like:
public class MyActivity extends Activity{
private List<String> mData = new ArrayList<String>();
private void runTask(){
new LoadStringsAsync(){
#Override
protected void onPostExecute(List<String> str) {
super.onPostExecute(events);
mData.clear();
mData.addAll(str);
}
}.execute();
}
}
You can send your list to a handler inside a Message :
Message msg = Message.obtain();
msg.obj = myList;
handler.sendMessage(msg);
More infos : http://developer.android.com/reference/android/os/Message.html
Related
Im sending data to background task to be processed but want to get the data back into tab1. This has got me flummoxed.
This is created from my activity
BackgroundTask backgroundTaskLogin = new BackgroundTask(Tab1Activity.this);
backgroundTaskLogin.execute(task,username,password);
I can see the data I want in backgroundtask
protected void onPostExecute(String result)
{
}
But cant get it back into my tab activity.. Help...
You need to use Interface which returns the result to the activity back.
/*Create an interface*/
public interface OnTaskCompleted {
void onTaskCompleted(Integer result);
}
/*Assign the values to the callback functions in AsyncTask*/
public class PerformTask extends AsyncTask<Integer, Integer, Integer> {
private static int counter;
private OnTaskCompleted listener;
public PerformTask(OnTaskCompleted listener) {
this.listener = listener; //Initialising listener
}
#Override
protected void onPostExecute(Integer result) {
listener.onTaskCompleted(result); //Assigning values to the callback function
}
}
/*Implement the Interface in you activity*/
public class MainActivity extends Activity implements OnTaskCompleted {
#Override
public void onTaskCompleted(Integer result) {
// The result contains the data you need
}
}
In my main activity I got an arraylist called data. I call an asynctask and do some stuff that gives me a different arraylist called values.
In the post execute of the asynctask I want to use items in 'values' to add some objects to 'data'. However, when debugging I noticed that the objects dont get added.
public class MainActivity extends Activity
{
ArrayList<DataItem> data;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
data = new ArrayList<DataItem>();
update();
}
public void update()
{
AsyncCallAWS thisTask = new AsyncCallAWS();
thisTask.execute();
}
private class AsyncCallAWS extends AsyncTask<String, Void, Void>
{
ArrayList<String> values = new ArrayList<String>();
protected void onPostExecute(Void result)
{
Log.i(TAG, "onPostExecute");
DataItem d;
for(String s : values)
{
d = new DataItem();
d.setValue(s);
d.setDataStreamName("test");
data.add(d);
}
}
//code to fill array
I'm guessing it's because I try to add items from the asynctask? Idk how to solve this, I need the data arraylist for a listview.
In AsyncTask class override method onProgressUpdate(), where you will add elements to array. Then in doInBackground() call publishProgress() for sending elements to onProgressUpdate(). Here http://developer.android.com/reference/android/os/AsyncTask.html -is great example.
private class TestAsyncTask extends AsyncTask<Object, String, Object> {
#Override
protected Object doInBackground(Object... params) {
String item = "";
//Do some stuff
publishProgress(item);
return null;
}
#Override
public void onProgressUpdate(String... value) {
data.add(value[0]);
}
#Override
protected void onPostExecute(Object result) {
}
}
I dont think you should create objects in the onPostExecute-method. Instead create it in the doInBackground-method of the class that extends AsyncTask, and then use set-methods in the onPostExecute-metod.
I want download details from web and update the UI within the doInBackground(),
For that I think I must get reference to activity within that method .How can I do it or is there another way to do that? What must be the something parameter? Or can’t update UI real-time?
public class DownloadActivity extends ListActivity {
public class DownloadItems extends AsyncTask<Something,Integer,Long> {
#Override
protected Long doInBackground(DownloadActivity... params) {
Toast.makeText(params[0], getIntent().getExtras().get("location").toString(), Toast.LENGTH_SHORT).show();
return null;
}
}
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
new DownloadItems().execute(Something);
}
}
You can either use a Handler or update your UI in onPostExecute(), which I recommend. Let your Async take care of its background logic and update the UI when that work is finished.
The best way is to simply move anything which affects UI into onPostExecute() because it's there to allow you to update the UI, it's the point of it.
There are other ways but when using AsyncTask there's really no reason not to use this.
public class DownloadActivity extends ListActivity {
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
new DownloadItems(this).execute();
}
public class DownloadItems extends AsyncTask<Something,Integer,Long> {
private Context context;
public DownloadItems(Context c){
context = c;
}
#Override
protected Long doInBackground(DownloadActivity... params) {
// Do something
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
Toast.makeText(context, context.getIntent().getExtras().get("location").toString(), Toast.LENGTH_SHORT).show();
}
}
}
You can create a constructor for passing or adding Context as a parameter.
public class DownloadItems extends AsyncTask<Something,Integer,Long> {
Context context;
public DownloadItems(Context cntx){
context = cntx;
}
#Override
protected Long doInBackground(DownloadActivity... params) {
//Toast.makeText(params[0], getIntent().getExtras().get("location").toString(), Toast.LENGTH_SHORT).show();
Toast.makeText(context, "String test", Toast.LENGTH_SHORT).show();
return null;
}
}
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
new DownloadItems(this).execute(Something);
}
By passing the context of the activity you can make any operation that are context related.
You can't execute UI operations in doInBackground(), you must do them in onPostExecute(). In DownloadActivity, you will create an instance of DownloadItems, and pass it the url where you want to download your stuff :
For example :
public class DownloadActivity extends ListActivity {
private void someMethod() {
DownloadItems yourTask = new DownloadItems(getApplicationContext());
yourTask.execute(yourUrl);
}
In the AsyncTask, you will do your download operations in doInBackground() and return the result so it can be handled by onPostExecute() :
public class DownloadItems extends AsyncTask<Something,Integer,Long> {
Context mContext;
public DownloadItems(Context context){
mContext = context;
}
#Override
protected String doInBackground(String... params) {
String theResult;
// download operations using url stored in params[0], and where you set theResult variable (for example...)
return theResult;
}
In onPostExecute(), you deal with the result, for example in your code above, you can call the Toast :
#Override
protected void onPostExecute(String result) {
Toast.makeText("YOUR TAG", result, Toast.LENGTH_SHORT).show();
}
You can call this in doInBackground:
runOnUiThread(new Runnable() {
public void run() {
//Your code
}
});
But isn't right... Please read the AsyncTask for more details, or use the onPostExecute to update UI...
In an existing app I have an activity with an inner class which extends AsyncTask, this looks like the following:
public class Activity_1 extends BaseActivity {
....
new async().execute();
...
public class asyncextends AsyncTask<Void, Void, String> {
protected String doInBackground(Void... progress) { ... }
protected void onPreExecute() { ... }
protected void onPostExecute(String result) { ... }
}
}
Now, I need to call the same doInBackground-method from another activity, but the onPostExecute() of the this inner class operates on some local UI variables and hence it's not possible to use it from outside the clas.
Is there any way I can call this AsyncTask, and just override the onPostExecute andonPreExecute-method, or shall I create yet another inner-class in the other activity, do the same background thing (of course move it to common utility-class or something), etc...?
You can make a separate abstract package private class, extending AsyncTask and implementing doInBackground() method:
abstract class MyAsyncTask extends AsyncTask<Void, Void, String> {
#Override
final protected String doInBackground(Void... progress) {
// do stuff, common to both activities in here
}
}
And in your activities just inherit from MyAsyncTask (new class probably should be private, by the way), implementing onPostExecute() and onPreExecute() methods:
public class Activity_1 extends BaseActivity {
...
new Async1().execute();
...
private class Async1 extends MyAsyncTask {
#Override
protected void onPreExecute(){
// Activity 1 GUI stuff
}
#Override
protected void onPostExecute(String result) {
// Activity 1 GUI stuff
}
}
}
If onPreExecute and onPostExecute contain some common actions as well, you can apply the following pattern:
abstract class MyAsyncTask extends AsyncTask<Void, Void, String> {
public interface MyAsyncTaskListener {
void onPreExecuteConcluded();
void onPostExecuteConcluded(String result);
}
private MyAsyncTaskListener mListener;
final public void setListener(MyAsyncTaskListener listener) {
mListener = listener;
}
#Override
final protected String doInBackground(Void... progress) {
// do stuff, common to both activities in here
}
#Override
final protected void onPreExecute() {
// common stuff
...
if (mListener != null)
mListener.onPreExecuteConcluded();
}
#Override
final protected void onPostExecute(String result) {
// common stuff
...
if (mListener != null)
mListener.onPostExecuteConcluded(result);
}
}
and use it in your activity as following:
public class Activity_1 extends BaseActivity {
...
MyAsyncTask aTask = new MyAsyncTask();
aTask.setListener(new MyAsyncTask.MyAsyncTaskListener() {
#Override
void onPreExecuteConcluded() {
// gui stuff
}
#Override
void onPostExecuteConcluded(String result) {
// gui stuff
}
});
aTask.execute();
...
}
You can also have your Activity implement MyAsyncTaskListener as well:
public class Activity_1 extends BaseActivity implements MyAsyncTask.MyAsyncTaskListener {
#Override
void onPreExecuteConcluded() {
// gui stuff
}
#Override
void onPostExecuteConcluded(String result) {
// gui stuff
}
...
MyAsyncTask aTask = new MyAsyncTask();
aTask.setListener(this);
aTask.execute();
...
}
I wrote the code from the head, so it might contain errors, but it should illustrate the idea.
Its so simple just Simply build an object of main class and than call the inner class like this
OuterMainClass outer = new OuterMainClass();
outer.new InnerAsyncClass(param)
.execute();
this answer is too late to help you but hope it help others.
Thanks
1.Create a constructor of AsynckTask in ClassOne.
2.Crate object or ClassOne by new keyword.
3.Call Async Task by object
ClassOne{
class AsyncParmas extends AsyncTask {
public ADDloadGeofenceDetails() {
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Object doInBackground(Object... params) {
}
}
Class ClassTwo{
ClassOne obj= new ClassOne ();
obj.new AsyncParmas ().execute();
}
}
GoodLuck Who were facing problem.
If we create one static method which is in one class and and will be execute in any class in doInBackground of AsyncTask we can easily update UI through same class and even in different class .
I have doInBackground(). after function I want to change some TextView on MainActivity.
but When I trigger the function on main activity I got NullPointerException on TextView line.
protected String doInBackground(Object... arguments) {
some code..
return result;
}
#Override
protected void onPostExecute(String result) {
if(result!=null)
new MainActivity().setScoreListUpdate(result);
}
MainActivity:
public void setScoreListUpdate(String settings)
{
String[] yeniscore = settings.split("\\|");
if(yeniscore.length > 1)
{
birinci.setText(yeniscore[1]); << NULLPOINTEREXC.
}
}
The reason this gives a NullPointerException is that you create a new instance of MainActivity instead of working on your existing one.
What you need to do is pass a reference to your Activity to the AsyncTask and then call your method on that reference.
So in your AsyncTask-class you will have a variable:
private MainActivity myMainActivity;
Add a constructor to your AsyncTask-class:
public MyAsyncTaskClassName( MainActivity activity ) {
myMainActivity = activity;
}
Then in onPostExecute you do:
myMainActivity.setScoreListUpdate(result);
Use
MainActivity.this.setScoreListUpdate(result);
instead of
new MainActivity().setScoreListUpdate(result);
in yout postExecute method.
Also, TextView called birinci should be a field in your MainActivity class, not just a variable in the onCreate method for example.
EDIT: It works like this in my program. Check out the differences.
public class DeviceSettingsStatsActivity extends ListActivity {
AsyncTask<Void, Integer, ListAdapter> task = null;
ListAdapter listAdapter = null;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
task = new ComputeTask().execute();
}
protected void viewComputeResult(ListAdapter result) {
setListAdapter(result);
}
private class ComputeTask extends AsyncTask<Void, Integer, ListAdapter> {
#Override
protected ListAdapter doInBackground(Void... params) {
// some stuff
}
#Override
protected void onPostExecute(ListAdapter result) {
DeviceSettingsStatsActivity.this.viewComputeResult(result);
}
}
}