I would like to cancel an AsyncTask in my Android application. The kicker is, my AsyncTask does NOT contain a loop, so I can't use break.
Here is my AsyncTask.doInBackground():
protected Void doInBackground(String... params) {
String location = params[1];
if(!location.matches("-?[0-9.]*,-?[0-9.]*")) {
try {
location = Util.getLatLngFromMapsQuery(location);
} catch (UnchainedAPIException e) {
setErrorCode(ERROR_GEO);
this.cancel(true);
}
}
UnchainedAPI unchainedAPI = new UnchainedAPI(YELP_KEY, YELP_SECRET, YELP_TOKEN, YELP_TOKEN_SECRET,
FOURSQUARE_ID, FOURSQUARE_SECRET, GOOGLE_PLACES_KEY);
try {
nonChains = unchainedAPI.getUnchainedRestaurants(params[0], location);
} catch (UnchainedAPIException e) {
setErrorCode(ERROR_API);
this.cancel(true);
}
if(nonChains.size() == 0) {
setErrorCode(ERROR_API);
}
return null;
}
What can I do here?
AsyncTask.cancel(boolean mayInterruptIfRunning)
does the trick.
or from inside the task:
cancel(true);
If you need to break the AsyncTask from doInBackground() just use
return null;
where you need to break. From onPostExecute() you can use
this.cancel(true);
Related
I am trying to return the content of a text file on localhost (wamp server) as a string. I can read the text file but I cannot return a string because the function run of Runnable is a void. I'm working on Android Studio (that's why I'm using thread).
public String serverToString()
{
String str;
Thread t = new Thread(new Runnable() {
public void run() {
try {
URL url = new URL("http://myIP/test.txt");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
str = in.readLine();
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Throwable th) {
th.printStackTrace();
}
}
});
t.start();
return str;
}
Advancing the the Cricket answer, I usually create an AsyncTask and inside it I define a callback interface.
The activity executing this task should implements this interface.
As an example of part of the code:
public class TeamUpdateTask extends AsyncTask, Object, TeamUpdateResponse> {
private TeamUpdateTaskCallback mListener;
#Override
public void onPostExecute (TeamUpdateResponse result) {
if (exception == null) {
mListener.OnTeamUpdateCompleted(result);
} else {
processException();
}
}
public void setListener (TeamUpdateTaskCallback listener) {
mListener = listener;
}
public interface TeamUpdateTaskCallback {
void OnTeamUpdateCompleted (TeamUpdateResponse response);
}
}
Hope it helps.
Generally, Volley library would be preferred over raw Thread. Or AsyncTask
but I cannot return a string because the function run of Runnable is a void
You can pass the result to a new method, though.
Define an interface
public interface ServerResponse {
void onResponse(String msg);
}
Add a parameter
public void serverToString(final ServerResponse callback)
{
String str;
Thread t = new Thread(new Runnable() {
public void run() {
try {
URL url = new URL("http://myIP/test.txt");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
callback.onResponse(in.readLine()); // This is the 'return' now
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Throwable th) {
th.printStackTrace();
}
}
});
t.start();
}
And instead of this
String response = serverToString();
Do this
serverToString(new ServerResponse() {
#Override
public void onResponse(String response) {
// handle message
}
});
I'm new im Java, and im trying to return with a defined string variable at the end of the function, but eclipse keeps saying that it's cannot be resolved to a variable, and wants me to define it. Probably it's because im define the variable within the Try{} brackets, but how else could i do it?
public class readtextfile extends AsyncTask<String, Integer, String>{
private TextView description;
public readtextfile(TextView descriptionTextView){
this.description = descriptionTextView;
}
#Override
protected String doInBackground(String... params) {
try {
URL url = new URL("http://example.com/description1.txt");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String line = null;
String result = "";
while ((line = in.readLine()) != null) {
//get lines
result+=line;
}
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
protected void onProgressUpdate() {
//called when the background task makes any progress
}
protected void onPreExecute() {
//called before doInBackground() is started
}
#Override
protected void onPostExecute(String result) {
this.description.setText(result);
}
}
Move the local variable declaration
String result = "";
to before the try block. If you define a variable within a block it's not available outside that block.
Alternatively you could move return result; to the end of the try block, but then you'd have to add another return statement at the end of the method, for the cases where an exception was thrown and got caught.
Or you could get rid of the try-block, move the exception-handling to elsewhere, and let any exceptions get thrown.
URL url = null;
String result = "";
Then inside your try, catch block.
try {
url = ....;
.
.
result = ....;
Declare the variable outside the try block.
I have an application in which an Android device is connected to a data acquisition system and the data is stored in a local db. I want to monitor in real time the data on a second Android as well. In order to enhance performance, I set up my own Apache server (XAMPP) on a Windows machine. I wrote two php scripts; one to store data in Memcache and one to get data from memcache. The Android devices are using HttpClient to call the scripts. I used memcache in order to eliminate some delays of writing to database. Below is the code used for sending and receiving the data... For testing, it is a simple loop (counter) with a thread delay. If I set the delay for 1 second, the textview is updated and runs smoothly. When I drop the delay to 0.1 seconds, it runs fine for a few seconds and then stutters (pauses) for 3-5 seconds. It continues this process of intermittent pausing while running. If I drop the delay to 0.01 seconds, the system crashes. My Apache server is connected to directly to my router. The Android devices are connected to my WiFi. My question is whether or not I'm doing something fundamentally wrong. I thought with memcache, I would easily be able to do 0.01 s sampling of data. Is my code properly handling the AsyncTasks? How can I prevent the Android system from apparently becoming "overloaded" with new tasks? It is as if I need a method to determine when a task is complete such that the next task can be called. I appreciate any feedback regarding php, httpclient, etc...anything that affects performance.
EDIT: My system no longer crashes when I drop the delay to 0.01 sec. I now have a catch for the null value in the onpostexecute method. However, I still get stutters/freezes.
private void startsendingdata() {
loop = 0;
if (sendingdatathread != null)
sendingdatathread.interrupt();
sendingdatathread = new Thread() {
public void run() {
while (loop < 5000) {
try {
runOnUiThread(new Runnable() {
#Ov
erride
public void run() {
new SendDataTask().execute();
loop++;
myvar = Integer.toString(loop);
}
});
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
};
sendingdatathread.start();
}
private class SendDataTask extends AsyncTask<String, Integer, Double> {
#Override
protected Double doInBackground(String... params) {
postData();
return null;
}
protected void onPostExecute(Double result) {
}
public void postData() {
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
// put all variables here (with connection code attached)
nameValuePairs.add(new BasicNameValuePair("connectioncode",
connectioncode));
nameValuePairs.add(new BasicNameValuePair("myvar", myvar));
httppostsend
.setEntity(new UrlEncodedFormEntity(nameValuePairs));
response = httpclient.execute(httppostsend);
response.getEntity().consumeContent();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void startgettingdata() {
if (gettingdatathread != null)
gettingdatathread.interrupt();
gettingdatathread = new Thread() {
public void run() {
while (true) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
new GetDataTask().execute();
}
});
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
};
gettingdatathread.start();
}
private class GetDataTask extends AsyncTask<String, Integer, Double> {
#Override
protected Double doInBackground(String... params) {
getData();
return null;
}
protected void onPostExecute(Double result) {
if (!line.isEmpty() && line!=null&&connectioncode.length() >= 6) {
tvLapTime.setText("MyVar: " + myvar);
}
}
public void getData() {
if (connectioncode.length() >= 6) {
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("connectioncode",
connectioncode));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
response = httpclient.execute(httppost);
entity = response.getEntity();
is = entity.getContent();
line = convertInputStreamToString(is);
response.getEntity().consumeContent();
} catch (ClientProtocolException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
// convert inputstream to String
private static String convertInputStreamToString(InputStream inputStream)
throws IOException {
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(inputStream));
String result = "";
while ((line = bufferedReader.readLine()) != null)
result += line;
try {
json = new JSONObject(result);
} catch (JSONException e1) {
e1.printStackTrace();
}
if (json != null) {
try {
myvar = json.getString(connectioncode + "myvar");
} catch (JSONException e) {
e.printStackTrace();
}
}
inputStream.close();
return result;
}
Do away with startsendingdata() and startgettingdata(). In the onPostExecute() of the tasks initiate the start of the next task. Now you are sure a task is finished before starting a new one. For instance you could start a timer which executes the next task.
I have done something like this in my code
public void doWork()
{
Job job = new Job("Job")
{
#Override
protected IStatus run(IProgressMonitor monitor) {
while (rsMemName.next()) {
Display.getDefault().syncExec(new Runnable() {
#Override
public void run() {
try {
String memId = rsMemName.getString("id");
if (doMemberTasks(memId)==false)
{
cnn.rollback();
return;
}
} catch (Exception ex) {
ex.printStackTrace();
try {
cnn.rollback();
return;
} catch (SQLException e) {
e.printStackTrace();
}
}
});
}
}
}
job.schedule();
}
What i want to do is exit from the whole method if doMemberTasks(memId) returns false.
But it doesn't return from the method and keep looping on ResultSet. how can i terminate the thread from the run method?
Please give any suggestions how could i achieve that.....
Thanks in advance....
This is because return will return only from the thread run method. What you can do is set a variable(flag) probably static, and check its value after the run code to put another return statement.
Yeah your best bet would be to have a flag,
boolean doWork = true;
...
while( doWork && rsMemName.next(){
...
if (doMemberTasks(memId)==false)
{
cnn.rollback();
doWork = false;
return;
}
I need to run two SwingWorkers. One of them can only run after the other is done. Can I run them like this?
class TestWorker {
private FirstWorker worker1;
private SecondWorker worker2;
public TestWorker() {
worker1 = new FirstWorker() {
#Override
protected void done() {
try {
result1 = get();
} catch (Exception) {
// exception handling
}
worker2 = new SecondWorker() {
#Override
protected void done() {
try {
result2 = get();
} catch (Exception) {
// exception handling
}
}
}
worker2.execute();
}
}
worker1.execute();
}
}
And how should I cancel them? Like this?
private cancel() {
if (worker2 != null) work2.cancel();
if (worker1 != null) work1.cancel();
}
Thanks a lot!
You can do it that way and it will work. However, unless there are other operations in your outer done that you're not showing, you would probably be better off with something that did both operations in doInBackground and returned an array of the results.