How to do or do nothing base on AsyncTask result? - android

Experts,
My goal is simple, input an address, click a button to test a URL, if not get the expected result, a toast info and then do nothing. If get expect result, continue the program.
Since I can not use URL in UI thread, I used AsyncTask, the problem is: though I know the result from AsyncTak, how to inform activity to do or do nothing?
What I want is a statement inside the OnClickListener like this:
if (result is not expected) return; else continue do things.
I cannot write above statement in onPostExecute, it will return onPostExecute(), not onClickLIstener().
Another is: even if I can pass the result to activity(namely to onClickLIstener()), when the result arrives, probably UI thread already run some other codes, but they shouldn't before knowing the result.
In short, I need the URL result to decide how to run remaining codes, therefore cannot use async task, what should I do?
Thanks.
Below is the example code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
btnConfirm.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new XXX().execute(code);
});
}
class XXX extends AsyncTask<String, Void, String> {
protected String doInBackground(String... strArr) {
XXXXX;
}
protected void onPostExecute(String result) {
XXXXX;
}
}

This should be easy. Try this approach:
Since you already have your AsyncTask as an inner class in your activity, you can easily return a result in onPostExecute() then check if request was successful or not.
Now, here is the final part: create a method in your activity like this:
private void executeOnAsyncSuccess(){
//place the code here you want to run
}
Now you can call it inside onPostExecute() easily!
You can also do this using Events but this approach should just work!
I hope this helps!

I just learned that maybe Callable is a good way, use its V get().

Related

Make operation only when activity is running

I have a loading activity which makes few requests to server and converts data.
And layout of this activity is just simple logo image and progressBar.
All my operations were made in onCreate() and according to received request from server I start different activities:
if (request == 1) { start activity A}
else { start activity B}
The problem is loading takes 2-3 sec and operations are made even before onResume(), before activity's view come to UI.
So its just blank activity which does some work.
How can I ensure that those operations are made only after activity complete its creation?
If i clearly understand you you want to start activity 0 in which onCreate function is doing internet requests and after getting feedback from it you decide to call activity A or B. Is that correct? If yes you need to do network request in backgroud so your user interface thread doesnt freez. You can use AsyncTask for example and on it's onPostExecute method decide to fire acitivty A or B
EDIT
private class YourAsyncTask extends AsyncTask<String, Long, String> {
protected Long doInBackground(String... params) {
//here is background thread work calling net API request, hard working etc... but you can't touch UserInterface thread, since we are in background
//here call your API and parse answear
String ret = flag
return flag;
}
protected void onProgressUpdate(Long... progress) {
}
protected void onPostExecute(String result) { //here you are getting your flag from doInBackground as a result parameter
// this is executed after doInBackground, fired automatically and run on User interface thread here you can for example modify layout so you can run activity A OR B
}
}
and if you have your logic in AsyncTask you can run it from onCreate for example it doesn't matter.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout);
new YourAsyncTask().execute();
}
So you layot will be displayed and after executed your onPostExecute will be called
You need to move that server call off the main ui thread. Use an IntentService or something similar.
What I understand from this question, you must be using AsyncTask or Service to connect to server. You put the main thread in while loop and AsyncTask or Service is doing the required operation for you. After operation is complete, it will break out of while loop and then use if/else loop and decide which activity to start next.
Something like this:
public void onCreate(Bundle savedInstanceState)
{
boolean isDone = false;
// initialization code here
// start AsyncTask
BackgroundThread.execute(params);
while(!isDone)
{
Thread.sleep(1000); // 1 sec
}
}
doInBackground()
{
// your code
isDone = true;
}
onPostExecute() is executed on main thread, not on background thread.

Understanding the UI thread

I am a beginner to Android and I have some confusions regarding Android UI Thread. Now, I know that no thread apart from the one that created the UI can modify it.
Great.
Here is the Activity from my first Android app which slightly confuses me.
public class NasaDailyImage extends Activity{
public ProgressDialog modalDialog = null;
//------------------------------------------------------------------------------
#Override
protected void onCreate(Bundle savedInstanceState){
//Instantiate progress dialog, skipping details.
Button b = //get reference to button
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
modalDialog.show(); // show modal
Toast.makeText(getApplicationContext(), "Getting feeds", 500).show();
new AsyncRetriever().execute(new IotdHandler()); // Get the feeds !!
}
});
}
//------------------------------------------------------------------------------
public synchronized void resetDisplay(boolean parseErrorOccured,
boolean imageErrorOccured,
IotdHandler newFeeds){
if(parseErrorOccured || imageErrorOccured){
// make a Toast
// do not update display
}else{
// make a Toast
// update display
// based on new feed
}
}
//------------------------------------------------------------------------------
class AsyncRetriever extends AsyncTask<IotdHandler,Void,IotdHandler>{
#Override
protected IotdHandler doInBackground(IotdHandler... arg0) {
IotdHandler handler = arg0[0];
handler.processFeed(); // get the RSS feed data !
return handler;
}
//------------------------------------------------------------------------------
#Override
protected void onPostExecute(IotdHandler fromInBackground){
resetDisplay( // call to update the display
fromInBackground.errorOccured,
fromInBackground.imageError,
fromInBackground);
}
//------------------------------------------------------------------------------
}
1. onCreate is on the UI thread so I can do whatever I want but onClick is not. Why can I make a ProgressDialog and a Toast in that method? Why no error there?
2. The AsyncTask is subclass of the the NasaDailyImage. This means it can access all the methods of NasaDailyImage including resetDisplay() which updates the display. resetDisplay() is called in the onPostExecute which runs on a different thread from UI. So, why can I update the display there and yet get no errors ?
onClick() is indeed on the UI thread. Most of what happens in an Activity happens on the UI thread.
onPostExecte() (and its counterpart onPreExecute()) runs on the UI thread as well. The AsyncTask.onPostExecte() documentation clearly states this. AsyncTask was deliberately designed such that developers could update the UI before and after they do background work.
In general, your code will be running on the UI thread unless you explicitly tell it otherwise. Once you create AsyncTasks, Runnables, or Threads, you need to ensure you understand where your code is executing. In an Activity, it is typically safe to assume you are on the UI thread.
You are extending AsyncTask class , where async task class is calling its sequential method automatically. First onPreExecute then doBackground and finally onPost. If you want to change any ui change you can use onProgressUpdate method.
To use your activity class simple call activityclass.this.resetDisplay(). Because inner class scope sometimes failed to integrate except global varible.
Thanks

Getting results from an AsyncTask

I'm trying to use AsyncTask to download a string and return the string. I want to use AsyncTask because it might take a while.
One problem is that nowhere on the internet can I find an example of an AsyncTask returning any kind of value. So I took the example in the Commonsware book and modified it to return a value and I get the value as follows:
String mystr = new AddStringTask().execute().get();
While this works, it seem that this line of code is waiting for the return value and therefore synchronous. There must be some way to have an event trigger with the results of the AddStringTask.
How is that done?
Thanks, Gary
An AsyncTask cannot return a value, because to get the returned value you would have to wait before the task is finished. That would make the AsyncTask meaningless.
Instead, you should move your code in onPostExecute() (which runs on the UI thread, if this is what you worry about). This is where you handle the value returned by doInBackground() and typically update the UI or show an error message.
Also if you wanted to implement a more general AsyncTask you could implement something like the following to compartmentalize your code inside the activity.
#Override
protected void onPostExecute(Bitmap r){
if (r != null) {
processListeners(r);
}
}
protected void processListeners(Object data) {
for (final AsyncTaskDone l : listeners) l.finished(data);
}
public void addAsyncTaskListener (final AsyncTaskDone l){
listeners.add(l);
}
Where AsyncTaskListener is an interface with one function called finished implemented in the Activity the same way an onClickListener would be.

AsyncTask: Using web services & threads

I am using AsyncTask on button click to refresh the screen. Following is the sequence of events that happen on btn click
progress dialog shows up
The doInBackground is called and thread is initialized which calls a web service. The web service fetches/uploads data. A pass/fail flag is set once the web service is called.
My problem is the onPostExecute is never called and therefore the screen is never refreshed.
And secondly by the time the data is downloaded and the web service sets the flag my code has already hit return stmt in doInBackground.
Question is how do i stop execution in my asynctask so that the web service is done downloading/uploading the data and finally execute onPostexecute.
FYI
I also get the following warning in eclipse
The method onPostExecute(boolean) from
the type
Screen.ConnectWebService is
never used locally
private class ConnectWebService extends AsyncTask <Void, Void, Boolean>
{
private final ProgressDialog pd = new ProgressDialog(screen.this);
protected void onPreExecute() {
pd.show(Screen.this, "Sync", "Sync in progress",true,false);
}
protected Boolean doInBackground(Void... unused) {
if (SyncInProgress == false)
{
CallWSThread();//creates thread which calls web service
}
Log.d("doInBackground","doInBackground");
return SyncStatus;
}
protected Void onPostExecute(boolean result)
{
pd.dismiss();
if (result==true) drawRadioButtons();
return null;
}
}
It should be:
protected Void onPostExecute(Boolean result)
As djg noted, you have a typo in your method declaration. You can avoid these kinds of mistakes by using the annotation #Override when you're implementing methods from a super class.

Toast and Async

I have a toast in a slave thread which needs to tell a user wen a connection is established. To do this I know I need to use Async to make the toast happen, but I'm not sure where or how to implements the extended async. If I understand it, I think I can just create a MyAsync with the and just onProgressUpdate() the toast?
#Override
public void onProgressUpdate(String... args) {
Toast.makeText(context, args, Toast.LENGTH_SHORT).show();
}
Thanks for your time
~Aedon
Yep, you should be able to just extend the ASyncTask and change the template variables to what you need. The Toast class is a static class so it can be called from any thread without worrying about conflicts.
I don't see any issues with your code above except you wouldn't want to be calling new Toast messages very often since they stack. So if you were to continuous call the .show() function it would stack them and continue to show new Toast messages every LENGTH_SHORT interval until it caught up.
As for an example of an ASyncTask, here you go:
private class MyAsync extends AsyncTask<<What to pass in to doInBackground>, <What to pass in to onProgressUpdate>, <What type onPostExecute receives>> {
protected T (result type to onPostExecute) doInBackground(T... urls) {
//Do big calculations in here
}
protected void onProgressUpdate(T... progress) {
//Update
}
protected void onPostExecute(T result) {
//Done
}
}

Categories

Resources