I had AsyncTask in my adapter class when i calling first time it's working fine. But when i call second time it doesn't work.
I know when we want to call same task multiple times in activity class we have to call new MyTask.execute().But here am created my task in non activity class (i.e Adapter class) so here am unable to instantiate my task. How can i resolve this problem? Please provide any solution.
This is my code:
public AsyncTask<String,Void,Void> mytaskfavorite = new AsyncTask<String,Void,Void>() {
protected void onPreExecute() {
pd = new ProgressDialog(mContext);
pd.setMessage("Loading...");
pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
//proDialog.setIcon(R.drawable.)
pd.setCancelable(false);
pd.show();
System.out.println("###########################################");
}
#Override
protected Void doInBackground(String...code) {
String buscode = code[0];
// TODO Auto-generated method stub
addFavoriteBusinessSelection.addFavoriteBusinessBusinessSelection(buscode);
System.out.println("##################################" + buscode);
return null;
}
#Override
protected void onPostExecute(Void res) {
pd.dismiss();
}
};
But here am created my task in non activity class (i.e Adapter class) so here am unable to instantiate my task.
That is not true. The you can initiate an AsyncTask from any class you wish with the guaranteed that doInBackground will be executed in a separate thread and the other methods in the called thread (usually the UI Looper thread).
To call it several types you should create a new class with it like that:
public Class TaskFavorite extends new AsyncTask<String,Void,Void>() {
// You can optionally create a constructor to receiver parameters such as context
// for example:
private Context mContext
public TaskFavorite(Context c){
mContext = c;
}
protected void onPreExecute() {
pd = new ProgressDialog(mContext);
pd.setMessage("Loading...");
pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
//proDialog.setIcon(R.drawable.)
pd.setCancelable(false);
pd.show();
// Don't use println in Android, Log. gives you a much better granular control of your logs
System.out.println("###########################################");
}
#Override
protected Void doInBackground(String...code) {
String buscode = code[0];
// TODO Auto-generated method stub
addFavoriteBusinessSelection.addFavoriteBusinessBusinessSelection(buscode);
System.out.println("##################################" + buscode);
return null;
}
#Override
protected void onPostExecute(Void res) {
pd.dismiss();
}
};
and then from your code (anywhere, adapter or activity, or fragment or even a loop you call)
TaskFavorite task = new TaskFavorite(getContext()); // how you get the context to pass to the constructor may vary from where you're calling it, but most adapters to have one
task.execute(... parameters...);
Related
In my old project, I used AsyncTask, but its deprecated so what method i used instead of this?
If we used thread, in AsyncTask having onbackground, onPreExecute and onPostExecute Override methods where this sections called in thread. Is there any alternative method. Can you please give me the solution?
Java code:
public class getDetailsfromWeb extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
if (paymentSync == null)
paymentSync = new ReceivePaymentSync(getActivity());
allCreditCardModel = new AllCreditCardModel();
allCreditCardModel = paymentSync.getGetCreditCardById(CrediCardId);
handler.post(allCreditRunnable);
return null;
}
/**
* #param string
*/
public void execute(String string) {
// TODO Auto-generated method stub
}
protected void onPreExecute() {
showProgress();
}
#Override
protected void onPostExecute(String result) {
progress.dismiss();
}
}
Just use a Thread.
The onPreExecute code goes in the constructor.
The doInBackground code goes in the run().
The onPostExecute code goes in the run of a runnable for runOnUiThread which you call at the end of the run().
This is a simple example, anyway I would give a look to the WorkManager library too:
Executors.newSingleThreadExecutor().execute(() -> {
Handler mainHandler = new Handler(Looper.getMainLooper());
//sync calculations
mainHandler.post(() -> {
//Update UI
});
//other sync calcs.
mainHandler.post(() -> {
//Update UI
});
});
I hope the question is I want to create a method which starts an AsyncTask, waits until the Task ends and then return the value which is provided in the onPostExecute method. So from my main I only want to call the method and get the value which is returned by te AsyncTask. Is that possible? And how does this method have to look like?
Just execute AsyncTask and do call the particular method which contains logic onPostExecute() method. See the example code what i have used.
protected void onCreate(Bundle savedInstanceState) {
customContactList = (ListView)findViewById(R.id.listView1);
ContactsAsyncTask newTask = new ContactsAsyncTask(this);
newTask.execute();
}
private class ContactsAsyncTask extends AsyncTask<Void, Void, ArrayList<String> >{
ProgressDialog dialog;
private SecondActivity context;
public ContactsAsyncTask(SecondActivity secondActivity) {
// TODO Auto-generated constructor stub
this.context = secondActivity;
}
protected void onPostExecute(ArrayList<String> result) {
super.onPostExecute(result);
context.useContacts(result);
}
public void useContacts(ArrayList<String> data) {
adapter = new CustomAdapter(SecondActivity.this,data);
customContactList.setAdapter(adapter);
}
Let say you have an instance of AsyncTask called task. In such case you do:
task.execute(parameters);
Result result = task.get();
Method get() will wait until task is completed and will return result from it.
P.S. You are trying to execute asynchronous task synchronously, which raises a question - "Do you need AsyncTask at all"?
my issue is the same as this
Instance variable of Activity not being set in onPostExecute of AsyncTask or how to return data from AsyncTask to main UI thread
but i want to send the data back to the same calling activity. Doesnt startActivity for intents always restart the activity
On option is to use listeners, where you create an interface that your activity implents, something like:
public interface AsyncListener {
public void doStuff( MyObject obj );
}
That way, if you're subclassing AsyncTask, it is easy to add this listener, then in onPostExecute(), you could do something like:
protected void onPostExecute( MyObject obj ) {
asyncListener.doStuff(obj);
}
This depends on your class structure, but if your AsyncTask is a class within your Activity then you can reference methods of that activity.
What you would do is in your onPostExecute method call a function of your Activity that passes some data that was retrieved in the AsyncTask to the activity where you can then use it..
The code would look like this
class YourActivity extends Activity {
private static final int DIALOG_LOADING = 1;
public void onCreate(Bundle savedState) {
setContentView(R.layout.yourlayout);
showDialog(DIALOG_LOADING);
new LongRunningTask1().execute(1,2,3);
}
protected Dialog onCreateDialog(int dialogId) {
switch(dialogId) {
case DIALOG_LOADING:
ProgressDialog pDialog = new ProgressDialog(this);
pDialog.setTitle("Loading Data");
pDialog.setMessage("Loading Data, please wait...");
return pDialog;
default:
return super.onCreateDialog(dialogId);
}
}
private void onBackgroundTaskDataObtained(List<String> results) {
dismissDialog(DIALOG_LOADING);
//do stuff with the results here..
}
private class LongRunningTask extends AsyncTask<Long, Integer, List<String>> {
#Override
protected void onPreExecute() {
//do pre execute stuff
}
#Override
protected List<String> doInBackground(Long... params) {
List<String> myData = new ArrayList<String>();
for (int i = 0; i < params.length; i++) {
try {
Thread.sleep(params[i] * 1000);
myData.add("Some Data" + i);
} catch(InterruptedException ex) {
}
}
return myData;
}
#Override
protected void onPostExecute(List<String> result) {
YourActivity.this.onBackgroundTaskDataObtained(result);
}
}
}
So the typical flow is like this, set the view of the current page, and then show a progress dialog. Right after that start the async task (or whenever, it doesn't matter really).
After your async task is complete, call a function of the activity and pass it the data.
Don't use shared data within the async task or you risk issues with threading.. Instead once you are done with it pass it to the activity. If you want to update the view progressively while doing work you can use on onProgressUpdate
Document doc = new Obtainer(context, uri).execute().get();
This code in the activity class renders the Obtainer(which extends AsyncTask) which gets the xml document from the url. This is the onPreExecute method:
protected void onPreExecute() {
super.onPreExecute();
System.out.println("Pre execute began");
exception = null;
dialog = new ProgressDialog(context);
dialog.setMessage("Loading started");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
System.out.println("Preexecute end");
dialog.show();
}
context is set in the Constructor:
public Obtainer(Context c, String addr) {
context = c;
address = addr;
}
During the runtime I can see in the console output both "Pre execute began" and "Preexecute end" but the progress dialog is not shown. What is the probleM?
Use this code, it works for me:
class Obtainer extends AsyncTask<Void, Void, Void> {
private ProgressDialog dialog;
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(App.this); // App - your main activity class
dialog.setMessage("Please, wait...");
dialog.show();
}
#Override
protected Void doInBackground(Void... params) {
// ...
}
#Override
protected void onPostExecute(Void result) {
dialog.dismiss();
}
}
And in your main activity class method call
new Obtainer().execute();
What Context are you passing when you create your Obtainer (AsyncTask subclass)?
If you are using the Application context via getApplicationContext(), it can not be used to create a Dialog (or any View for that matter). You need to pass it a Context that can create Views.
"If you're in the habit of using your application context (from a call to getApplicationContext(), for example) in places where you need a Context to create views, it's only a matter of time until you find a case where things don't work quite like you would want or expect."
From: https://plus.google.com/107708120842840792570/posts/VTeRBsAeyTi
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();
}
}