I'm begining with Android development. I have an asynchronous operation, but my intention is wait the operation is completed, and after that, continue the execution of my program.
I have used AsyncTask, and all its methods, but I got error, because on the onPreExecute method I want to show another Activity, so I guess I can't show another Activity. That's the reason I want to wait to complete the asynchronous operation.
Greetings
1st edit:
I've used AsyncTask(onPreExecute, doInBa..., onPost... ), but none method works. I understand how it works the AsyncTask class, but I want stop the execution when I invoke one asynchronous thirdparty method, because in the listener that needs, I change the value of a String variable X, and after invoke my method, that uses the thirdparty method, I use the variable X. I got an exeption because the variable hasn't updated.
Please, read and follow example of AsynTask. You need to override onPostExecute
Not entirley sure what the question is but AsynTask has a method that you can call after everything has completed. A good practice is to have a dialog or a spinner showing that work is happening then dismiss it.
class loadingTask extends AsyncTask<String, Void, String> {
protected String doInBackground(String... urls) {
//Do work
}
protected void onPostExecute(String s) {
ShowProgress.dismiss();
Intent myIntent = new Intent(this, PostExAct.class);
startActivity(myIntent);
}
}
In your on create:
ShowProgress = ProgressDialog.show(MainActivity.this, "",
"Loading. Please wait...", true);
new loadingTask().execute("params here");
This will show a loading dialog and while the work is being done then will be dismissed when the work is finished.
Related
I'm new to learning java. I have been working how i can do it for 2 days. I will be mad. Please help me
I want that when my function run, all activity must wait until my function is finished.
an example
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
setContentView(R.layout.activity_main);
webView2 = (WebView) findViewById(R.id.webView);
Log.v("htmlg","oncreate started");
main_command();
/*
*
* main_command(), When this command run application must wait in here.
*
* */
Log.v("htmlg", "oncreate finished");
}
public static int finished = 0;
public void main_command(){
/*
*
* There is some webview actions in here. it takes about 5 minutes.
*
* When webview operations are finished.
* I call javascript command javascript:window.HTMLOUT.ok();
* I want everything wait until webview operations are finished and javascript command runned.
*
* */
}
But I could not do it with no way. When main_command() runned, Log.v() function will run after it immediately. but main_command() is still running and it is not finished. when it finished a javascript command will call a function inside android. then process will be finished and application can continue to work where it was.
Now, I'm telling my experiences.
I tried to write webview codes inside Asynctask but I could not use webview inside asynctask.
i put webview inside rununithread() inside asynctask, i could not do again.
i tried to put main_command() inside CountdownTimer but "oncreate finished" line runned before CountdownTimer finished.
Now i feel helpless. I dont know java or android programming so much. I am php programmer. I try to do webview application. I dont understand java structure so much. If you can do , can you write correct example working code ? Because I dont understand all examples. I looked and read everything maybe there was solution but I could not understand it. I need your help.
Thanks
You don't want to block the main thread, otherwise the android system will show "Application not responding" error. And your users will most probably choose to kill the app.
From what I understand, you want your application to resume when you call it through a javascript command. This is how you can proceed:
Make a function postMainCommand(). In this method, write everything that needs to be executed after that javascript command call. I mean the ones like:
Log.v("htmlg", "oncreate finished");
Call this method after your web-work is complete.
Till your job is in progress, you can show a non-cancelable progress-dialog with some text like "Please wait...". Or, if you can keep track of the progress, you can keep updating the message:
ProgressDialog dialog = new ProgressDialog(this);
dialog.setMessage("Please wait...");
dialog.setCancelable(false);
dialog.show();
Non-cancellable because you don't want the user to interact with the app in-between, right?
When your webview job is over, call dialog.cancel();
I have a class, that executes some command in background. Class method is executed asynchronously (by using AsyncTask) and when command finishes, it posts event with command result. Then, new activity is started. To do this, I added inside OnCreate method to MainActitity:
ssh = new SshSupport();
ssh.Connect();
ssh.ExecuteCommand(commandType);
//..................................
ssh.eventHandler = new ISshEvents()
{
#Override
public void SshCommandExecuted(SshCommandsEnum commandType, String result)
{
if (progressDialogExecuting.isShowing()) progressDialogExecuting.dismiss();
Intent intent = new Intent(MainActivity.this, ResultListActivity.class);
intent.putExtra("result", result);
intent.putExtra("commandType", commandType);
startActivity(intent);
}
So it works as should. My commands starts in background and when finished, my event fires and displays new activity with results (all results are received via getIntent().getExtras() and then formatted to be displayed as should).
Problem: on result activity I have "Refresh" button. When pressed, all data should be refreshed. So I need to execute ssh.ExecuteCommand(commandType); again to get refreshed data. Note that I don't want to open new ssh connection for this. Instead, I want to use already opened connection and simply execute my command again.
So I made my 'ssh' static and I used MainActivity.ssh.ExecuteCommand(commandType); on refresh button press. It works, but obviously, it causes to create second instance of ResultListActivity, instead of refreshing data on existing one.
I can even avoid to creating result activity again by checking if it's already exists (for example by adding 'active' boolean static variable to it). However, it won't help me because I still have no any possibility to refresh data inside my existing activity.
So, how can I do it?
No responses, so I'm answering to my own question. My solution was:
- Change my activity launchMode to singleTop
- Override method onNewIntent
In this case each time I start this activity: if activity already exists it won't be created again. Instead, onNewIntent method will be called.
http://developer.android.com/guide/topics/manifest/activity-element.html#lmode
http://developer.android.com/reference/android/app/Activity.html#onNewIntent%28android.content.Intent%29
However, I'm not sure if approach like this is good. How do you think?
I am trying to create a lot of asynctask, and run one by on in order.
Is it possible? I can't find any solution for this.
onPostExecute and then call a new AsnycTask again is not a good solution for me.
SO what I want:
async1.execute
async2.execute
async3.execute
async1.over->async2.start
async2.over->async3.start
If you use the serial executor (default in API 11 and above), this happens automatically. If you need this to work before API 11, you need to do the classic wait/notify trick (https://www.science.uva.nl/ict/ossdocs/java/tutorial/java/threads/waitAndNotify.html)
Do like
async1.execute
then write async2.execute into onPostexecute of async1
and then write async3.execute into onPostexecute of async2
There is no any other valid way. You can think about to implement threads (wait/notify), but that is not for asyntask.
I guess you should use Executor whit BlockQueue instead of AsyncTask, and use Handler to send handle the result. BockQueue is a FIFO data structure, and fit your flavor...
// Async Task Class here async1
class YourAsynClass extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Shows Progress Bar Dialog and then call doInBackground method
showDialog(progress_bar_type);
}
#Override
protected String doInBackground(String... PassYourdata) {
// do your stuff here
}
#Override
protected void onPostExecute(String IFYouwantPassData) {
// Dismiss the dialog
dismissDialog(progress_bar_type);
// here async2
new SecondAsyncTask.execute(Passeddata);
}
}
and in the third one do the same
Let the first AsyncTask is MyAsyncTask1 and the second one is MyAsyncTask2. Now what you want is.
Execute the MyAsyncTask1 from with in the activity
Take the response received
Now on successfull response,execute the MyAsyncTask2
what about calling them in sequence like:
MyAsyncTask1.execute();
MyAsyncTask2.execute();
The problem with the above code can be understood by the fact that calling execute on the AsyncTask object will create a new thread to run in different memory space,and immediately the next AyncTask will be started with in its own memory space.But that was not what we want.We want that the first thread must finish its working and only then the second one will start to work.How this can be achieved?
The answer lies in the onPostExecute().This is the method which will help you to get rid of this situation.While you call execute on MyAsyncTask1 then after doInBackground() of the first AsyncTask its,onPostExecute() will be called .Place a check in that onPostExecute() that if response is null, if received response is not equal to null,and is a valid response then call execute on the MyAsyncTask2(with respective parameters if specified).
SEE THIS
You can do this in a chain.....
So, I want to display an image in an ImageView that is downloaded from a website and saved on the device's file system. The downloading of the image is done by calling a method in another class (in one of my separate library projects). This method, in turn, calls an AsyncTask to do the downloading in another thread. On the post execute of this AsyncTask, I want to set the image for the ImageView. Keep in mind that this separate library is independent of my main app and knows nothing about my UI (and I wish to keep it this way).
I have a method in the UI portion of my code (in a fragment) that sets the image for this ImageView. I'm thinking it would be nice to pass this method to the library method that retrieves the image. That way, when the download is complete, onPostExecute() could call this UI method that I have. The dilemma I'm facing is I don't want any compile-time dependencies for my library that references my UI/ImageView.
Finally, not every time when this AsyncTask is called do I want to do anything in the post execute. In other words, any post execute logic is completely optional.
General Flow:
1) Code in my fragment calls MyLib.saveRemoteFile(url, destinationFilename)
2) MyLib.saveRemoteFile() downloads the image and saves it to a file by way of a thread (via an AsyncTask)
3) As soon as the image is downloaded and saved, I want to set the ImageView.setImageBitmap() using the bitmap from the saved file
I've looked at the Command pattern, but am stuck on how to implement it in this particular scenario. Any tips on this?
Maybe there is another approach that can be used? (without MyLib.saveRemoteFile() having compile-time dependencies to the UI)?
UI Fragment code snippet:
.
boolean wasSaved = MyLib.saveRemoteFile(url, destinationFilename, true)
.
.
.
Library code snippet (in a different library project):
public static boolean saveRemoteFile(String url, String filename, boolean overwriteExistingFile)
{
.
// code to check if directory exist and creates it if needed, etc, etc...
.
.
.
new AsyncTask<String, Void, Boolean>() {
#Override
protected Boolean doInBackground(String... params)
{
// code to download and save image file...
.
.
.
}
#Override
protected void onPostExecute(Boolean result)
{
// *** this is where I want to take the ImageView and set its bitmap image.
}
}.execute(new String[] {url, filename});
return retVal;
}
Design is flawed, library should have provided you Observer design pattern, using which you would have submitted listener reference along with downloading details.
Upon finishing downloading, library using your provided listener would have notified back to you over download process result, reading which you could have taken action easily with UI.
Moreover in your library code saveRemoteFile() spawns a asynctask, return value is irrelevant here as method wont wait until asynctask is executed.
Possible implementation as per above mentioned info.
// Interface for bserving
public interface DownloadListsner{
public void onSuccess(String uri);
public void onError(String uri);
}
// API for submitting download request
public void saveRemoteFile(String url, String filename,DownloadListsner listener... ){
...
}
AsyncTask{
// Upon finish execution
onPostExecute(){
// Take action
listener.onSuccess
or
listener.onError
}
}
Command pattern
You should be rather implementing Observer pattern and your download library should allow other code to attach listeners and be notified about when certain action is completed/started/whatever. And since you are just being informed that something happened you can have your code that reacts on that notification completely different in every part of your app if you need so.
I have a really weird problem, which I am unable to debug so far...
Thing is...my app needs to download something to work. So in the beginning of the onCreate() method, I check if that something is already downloaded. If not, I pop a dialog up asking the user to download it.
if (!isInstalled) {
showDialog(DIALOG_INSTALL);
} else {
start();
}
Where start() method performs some other action. Now, that showDialog calls this:
builder = new AlertDialog.Builder(MyApp.this);
builder.setMessage("Would you like to install...")
.setCancelable(false)
.setPositiveButton("Install", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
aManager.install(MyApp.this);
}
});
dialog = builder.create();
return dialog;
My dialog is shown and I am clicking, so aManager.install() is called. I am passing the context because that aManager.install() pops up a ProgressDialog to show downloading progress and spawns a new thread in which everything is downloaded. So obviously before creating my dialog I make a Handler to receive the response from that aManager.install(). And the response MAY vary, because for example the internet connection isn't available (Exception raised and catched and listener called with different code).
Now, when that happens (Exception) I would like to call another dialog saying "something went wrong, would you like to retry?"...so another call to showDialog(DIALOG_REINSTALL) (this time with another code).
Thing is...the showDialog() gets called (I can verify this by logging) but the dialogs doesn't show up. Instead my application JUST HANGS!?!?!?
Does someone have a clue why it's doing this???? No exception raised, absolutely nothing from logcat, I can't tell WHERE it's hanging...just see that the method is called and the dialog should be displayed...
Thank you very much!!
Looks like you have a deadlock. I would put the download code on the separate thread e.g. use AsyncTask. In task.onPreExecute() you can dismiss 1st dialog and pop-up your progress dialog which you update by overwriting task.onProgressUpdate()
Use .show() instead of .create().