I would like to do step by step upload date to web service.
My code:
private Thread WebServiceThread;
public void onCreate(Bundle savedInstanceState) {
//...
WebServiceThread = new WebService();
WebServiceThread.start();
}
private class WebService extends Thread {
public void run() {
try {
new WebServiceUpload().execute("");
} catch (Exception e) {
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT)
.show();
}
}
}
private class WebServiceUpload extends AsyncTask<String, Void, String> {
protected String doInBackground(String... data) {
// upload part
}
protected void onPostExecute(String result) {
//...
WebServiceThread = new WebService();
WebServiceThread.start();
//<Tab>__what to do here__</Tab>
//...
}
}
Now can run, but cause the device slow.
Please tell me how to close parent thread or restart parent thread way to solve this problem. (or other practice to same target.)
You don't have to chain threads like that. Just create a single AsyncTask extension that uploads the data step by step in doInBackground. If you want to publish progress reports, you can do that by calling publishProgress.
Your method of creating a WebServiceUpload from a worker thread is really bizarre and will most likely not work. AsyncTask is designed to be started from the UI thread. Just call your new WebServiceUpload().execute() from the main thread when you want to start the upload steps.
In your onPostExecute check if thread is running then force it to stop.
protected void onPostExecute(String result) {
//...
**if (WebServiceThread.isAlive())
WebServiceThread.stop();**
WebServiceThread = new WebService();
WebServiceThread.start();
//<Tab>__what to do here__</Tab>
//...
}
Related
I am running an AsyncTask in MainActivity and making it sleep for 10 seconds in the doInBackground() method. And in between (before the 10 seconds are over), I press the Home button and I am also updating the text in TextView in the onPostExecute() method of the AsyncTask. My AsyncTask is able to update the view successfully even though my app is in background.
I am not sure how that is possible, by the way, if I press the Back button, then I can see the onDestroy() method of the activity being called, but still there is no exception when the onPostExecute() method tries to update the TextView.
public class MainActivity extends AppCompatActivity {
private TextView finalTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
finalTextView = (TextView) findViewById(R.id.finalTextView);
AsyncTaskRunner task = new AsyncTaskRunner();
task.execute("10", "11", "12");
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.e("onDestroy", "ActivityDestroyed");
}
private class AsyncTaskRunner extends AsyncTask<String, String, String> {
private String resp;
#Override
protected String doInBackground(String... params) {
publishProgress("Sleeping..."); // Calls onProgressUpdate()
try {
int time = Integer.parseInt(params[0]) * 1000;
Thread.sleep(time);
resp = "Slept for " + params[0] + " seconds";
} catch (InterruptedException e) {
e.printStackTrace();
resp = e.getMessage();
} catch (Exception e) {
e.printStackTrace();
resp = e.getMessage();
}
return resp;
}
#Override
protected void onPostExecute(String result) {
// execution of result of Long time consuming operation
finalTextView.setText(result);
Log.e("onPostExecute", "" + result);
}
}
}
Before jumping to any conclusion you should know how async task works
Go thorugh this answer which may solve half of your problem
One more thing like
Async task works on UI thread of the application
what-is-the-android-uithread-ui-thread
AsyncTask won't stop even when the activity has destroyed
Go read the reference docs on AsyncTask to understand how the threads interact and which methods run on which thread.
AsyncTask | Android Developers
Hi onCancel of dialog i want to cancel to server call but i m facing problem that even i cancel the task, it hits my server and modifies the data. How can I resolve this issue ? Below is my code..
private class UserBoardingTask extends AsyncTask {
#Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(getActivity());
progressDialog.setMessage(getResources().getString(R.string.please_wait));
progressDialog.setIndeterminate(false);
progressDialog.setCancelable(true);
progressDialog.setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
if (userOnBoardingTask!= null && userOnBoardingTask.getStatus() != AsyncTask.Status.FINISHED && !userOnBoardingTask.isCancelled()) {
userOnBoardingTask.cancel(true);
}
}
});
progressDialog.show();
}
#Override
protected Void doInBackground(String... urls) {
String boardingURL=null;
boardingURL= getUrl();
UserOnBoardingDTO userOnBoardingDetailsDTO = AppStateManager.getUserBoardingDetails();
try{
RestAPIManager.putToNSWebService(boardingURL, userOnBoardingDetailsDTO, username, password);
}
catch (Exception e) {
errorMessage=getResources().getString(R.string.unknown_exp);
}
return null;
}
#Override
protected void onCancelled() {
super.onCancelled();
closeProgressDialog();
errorMessage="";
AppStateManager.setUserBoardingDetails(null);
userOnBoardingTask=null;
}
#Override
protected void onPostExecute(Void res) {
closeProgressDialog();
userOnBoardingTask=null;
if(!FieldsValidator.isBlank(errorMessage)){
CommonUtil.showToast(getActivity(),errorMessage);
errorMessage="";
return;
}
Just check isCancelled() once in a while:
protected Object doInBackground(Object... x) {
while (/* condition */) {
// work...
if (isCancelled()) break;
}
return null;
}
and another solution is
protected void onProgressUpdate(String... progress1) {
if(condition){
break;
}
}
Move the dialog out of the async task and only start the task when the dialog is not canceled.
Actually the problem is not termination of your asynsTask but the server hit if a server hit is already done before termination of asynsTask then you must interrupt your server request also.Just terminate your server request using abort method.
Where is userOnBoardingTask declared and where it is assigned to a reference to running task? I suspect this does not store a proper reference when the task tries to cancel it.
I am not sure if it is the actual reason of your problem. But for sure you may get rid of this variable if it is intended to pint at current task. Just change dialog's on cancel listener:
private class UserBoardingTask extends AsyncTask<String, Void, Void> {
#Override
protected void onPreExecute() {
// ...
progressDialog.setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
if (UserBoardingTask.this.getStatus() != AsyncTask.Status.FINISHED
&& UserBoardingTask.this.isCancelled()) {
UserBoardingTask.this.cancel(true);
}
}
});
In fact you may omit UserBoardingTask.this phrase as the inner class can point directly fields of nesting class as far as the names are not obscured by the names of inner class members:
private class UserBoardingTask extends AsyncTask<String, Void, Void> {
#Override
protected void onPreExecute() {
// ...
progressDialog.setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
if (getStatus() != AsyncTask.Status.FINISHED && isCancelled()) {
cancel(true);
}
}
});
EDIT
Another point is that before sending request to the server you may check inside doInBackground you may check if the task has not been cancelled
// ...
#Override
protected Void doInBackground(String... urls) {
// ...
try {
if(isCancelled()) {
throw new Exception("Exit: task cancelled!");
}
RestAPIManager.putToNSWebService(boardingURL, userOnBoardingDetailsDTO, username, password);
// ...
RestAPIManager.putToNSWebService(boardingURL, userOnBoardingDetailsDTO, username, password);
This above code hit the server. So you have to validate the execution of code inbetween cancellation.
Try something like this
try{
if(!userOnBoardingTask.isCancelled())
{
RestAPIManager.putToNSWebService(boardingURL, userOnBoardingDetailsDTO, username, password);
}
}
catch (Exception e) {
errorMessage=getResources().getString(R.string.unknown_exp);
}
This is ok. If user cancel the task before ResetAPIManager code executes. Suppose user try to cancel the task after server call initiated you have to tell already modified or remodify server data or unable to cancel or some message to user. All done through getting server reponse and validate server response if it changed or not.
Use something like this
Var rsponse = RestAPIManager.putToNSWebService(boardingURL,userOnBoardingDetailsDTO, username, password);
Validate the reponse message in onPostExecute() or OnCancelled() method.
If you cancel the asynctask after access this method
RestAPIManager.putToNSWebService(boardingURL,userOnBoardingDetailsDTO, username, password); the async task will cancel after running the above code so you should correct this by creating a new method inside RestAPIManager class and call that method inside OnCancelled method from your asyncTask.
Short Anser: Its not possible stop data posts thru a simple cancel. once an async task runs even if you cancel it mid way data posts will occure. Cancellation can be done in a Simple Run
Check this Post
[Android - Cancel AsyncTask Forcefully
I've got a simple login screen. If you click "Login", a progress bar should appear while we wait for the AsyncTask in the background to check the login credentials.
If I run the code without the AsyncTask in the background, my progress bar appears immediately. However, if I use the AsyncTask, which I set up after I make my progress bar appear, the app freezes at the exact moment I click on "Login". Then it waits until the AsyncTask has got its result (get() command) and only then it unfreezes, making my progress bar useless.
Is this a commonly known issue? How do you solve it?
This is how where I set up the AsyncTask, after I show the progress bar.
showProgress(true, "Logging in ...");
mAuthTask = new InternetConnection();
String arguments = "email="+mEmail+"&pwd="+mPassword;
boolean k = mAuthTask.makeConnection("ADDRESS", arguments, getBaseContext());
String f = mAuthTask.getResult();
And this is my AsyncTask. downloadUrl() sets up an HttpURLConnection. This works, I tested it.
private DownloadData data = new DownloadData();
public boolean makeConnection(String url, String arguments, Context context) {
if(isWifi(context) || isMobile(context)) {
argsString = arguments;
data.execute(url);
return true;
} else {
return false; //No network available.
}
}
public String getResult() {
try {
return data.get();
} catch (InterruptedException e) {
return "Error while retrieving data.";
} catch (ExecutionException e) {
return "Error while retrieving data.";
}
}
private class DownloadData extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... url) {
try {
return downloadUrl(url[0]);
} catch (IOException e) {
return "Unable to retrieve data.";
}
}
Do it like:
#Override
protected void onPreExecute() {
Asycdialog.setMessage("Working");
Asycdialog.getWindow().setGravity(Gravity.CENTER_VERTICAL);
Asycdialog.getWindow().setGravity(Gravity.CENTER_HORIZONTAL);
Asycdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
Asycdialog.setCancelable(false);
//Dialog Show
Asycdialog.show();
super.onPreExecute();
And then in onPostExecute:
protected void onPostExecute(String result) {
// hide the dialog
Asycdialog.dismiss();
super.onPostExecute(result);
}
To use the same Async task from Different classes:
class MainActivity{
new MyTask().execute();
}
class DifferentActivity {
new MyTask().execute();//a new instance
}
class MyTask extends AsyncTask{
public MyTask(Context context){
}//Pass in context.
}
Pass the context to the constructor, if you want a consistent Progress dialog.
TO publish the progress from doInBackground you can use the following:
publishProgress(progress);
Asycdialog.setMax(lines);
Asycdialog.incrementProgressBy(1);
Where progress is a string, lines are the max number of items.
You should not call get() it blocks the ui waiting for the result to be returned making asynctask no more asynchronous.
You have
private DownloadData data = new DownloadData();
and you have
data.get(); // this why it freezes
and
private class DownloadData extends AsyncTask<String, Void, String>
http://developer.android.com/reference/android/os/AsyncTask.html#get()
You only need
data.execute(url);
And if your asynctask is an inner class of activity class you can return result in doInbackground and update ui in onPostExecute. If not you can use interface as a callback to the activity to return the result.
your issue is related to the fact that you are calling getResult from the UI Thread. getResult calls data.get() that is a blocking operation. That's why you are getting a freeze. Your UI Thread is waiting for get() to complete and it is unable to draw everything else
I have an async task that goes to DB and fetches data. once in a while, the DB connection is lost and I'm getting an exception while I'm inside the async task and the application crushes.
My question is there a way to catch the connection lost exception while I'm in the async thread and publish a message to user that the connection was lost and prevent my application from crushing.
Thanks in advance for your help.
Alex
Step #1: Store the Exception in a data member of the AsyncTask, when you catch it in doInBackground()
Step #2: In onPostExecute(), if you have an Exception stored in that data member, do something with it (e.g., display a crouton).
You can do it as below:
private class GetData extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... params)
{
try{
//Access DB here
return "Success";
}
catch(Exception e)
{
return "Exception"
}
}
#Override
protected void onPreExecute()
{
}
#Override
protected void onPostExecute(String result)
{
if (result.equalsIgnoreCase("Success"))
{
//Do your operation
}
else if (result.equalsIgnoreCase("Exception"))
{
//Display Exception here
}
}
}
I have a base class of an activity and a sub class which extends the base class. The superclass has a async task to perform some action. I call this by running it on the ui thread since otherwise it throws an IllegalInitializerError:
superclass.this.runOnUiThread(new Runnable() {
public void run() {
String p="";
try {
p=new asynctasker().execute().get();
}
}
}
In my async task:
protected void onPreExecute()
{
// TODO Auto-generated method stub
super.onPreExecute();
//showDialog();
Log.d("Now","Inside right now");
dialog = ProgressDialog.show(class_create_event.this, "Loading1", "Please Wait");
}
However the dialog is displayed almost at the end of the request. The I am in part is printed correctly. I know that something is blocking my ui thread. But if I dont call the async task from the UI thread it throws an illegal initializer error. Is there any way out?
You don't need to have UIthread for calling AsyncTask
Call it like this way
FetchRSSFeeds async = new FetchRSSFeeds();
async.execute();
private class FetchRSSFeeds extends AsyncTask<String, Void, Boolean> {
private ProgressDialog dialog = new ProgressDialog(HomeActivity.this);
/** progress dialog to show user that the backup is processing. */
/** application context. */
protected void onPreExecute() {
this.dialog.setMessage(getResources().getString(
R.string.Loading_String));
this.dialog.show();
}
protected Boolean doInBackground(final String... args) {
try {
// Fetch the RSS Feeds from URL
// do background process
return true;
} catch (Exception e) {
Log.e("tag", "error", e);
return false;
}
}
#Override
protected void onPostExecute(final Boolean success) {
if (dialog.isShowing()) {
dialog.dismiss();
}
if (success) {
// Setting data to list adaptar
setListData();
}
}
}