Handle AsyncTask in Class - android

I am using AsyncTask Class to handle images that are coming from the server to display it in the ImageView I have one Next button in my code to call the next image using following code:
private class LoadImage extends AsyncTask<Void, Void, Void> {
#Override
protected void onPostExecute(Void result) {
if (imgque != null) {
imgSelectedQue.setImageDrawable(imgque);
if (getActivity() != null) {
adjustResourceEnvelope();
}
}
}
#Override
protected void onPreExecute() {
imgque = null;
imgSelectedQue.setImageDrawable(null);
imgSelectedQue.requestLayout();
}
#SuppressWarnings("deprecation")
#Override
protected Void doInBackground(Void... params) {
InputStream is;
try {
is = (InputStream) new URL(Constants.PLAYER_SERVICE_BASE_URL + "/playerservice"
+ imageurl).getContent();
imgque = Drawable.createFromStream(is, null);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
imgque = null;
e.printStackTrace();
}
return null;
}
}
Now the issue is that if I click the next button REPEATEDLY then it call the AsyncTask that many times and ImageView displaying all the images like "Slide-Show" because all the url images are in queue.
Is there any way to display only last AsyncTask call image?

Do something like this:
[1] When you call LoadImage AsyncTask on click of NEXT button disable NEXT button.
[2] On onPreExecute() method of your LoadImage AsyncTask enable your NEXT button again.
OR,
You can achieve such things with use of simple FLAG also. By setting it as true and false.
Hope this helps you.
Thanks.

I Found the Solution for this.If anyone facing the same issue.
I Added new lines
if (loadimage != null)
{
loadimage.cancel(true);
loadimage = null;
}
loadimage.cancel(true) will stop the AsyncTask if it is already Running
then execute the AsycTask()
loadimage = new LoadImage();
loadimage.execute();
In this way i am able to call only last AsyncTask that what I required.

Related

Best approach to make a login screen

I am writing here because this is my last solution of understanding this type of programming.The problem is that I got stuck on what to use to handle the connection to a server and log-in. Should I use async task, handler or thread ? I didn't find a concrete answer stating which one to use, only found that async task is used to download images or other download stuffs.
Until now I have used a thread to connect to the server. The problem I encountered was when I catch the exception ( Putting invalid username/password ) and try to log-in again. ( I needed to "close" the last thread and start one again )
After this I started to use async task but I don't really understand how it should work and I am stuck on a toast of invalid username/password.
private class connectStorage extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
try {
api = DefaultClientFactory.create(host, getUser, getPassword);
if (api.getAuthToken().trim().length() > 3) {
//TO DO LAYOUT CHANGE;
}
} catch (StorageApiException e) {
e.printStackTrace();
Log.i("TEST", "" + e.getMessage());
}
return null;
}
Also, I am 100% sure that calling inflate in the doInBackground method won't work too ( there I wanted to change the activity ).
I am starting the async task on a button press.
When you are using asynctask
You have doInBackground and onPostExecute
So basically get a json or string or boolean as a result from doinbackground
and in onpostexecute check if the login in succesful or not if its succesful save the data from server and start an intent to go to another activity or toast the user that that user login details are wrong and try again.
So your asynctask can be an inner class of your activity class which is login and onClickSubmit button call the asynctask class and on post execute parse the json and according to the result decide what to do
Example:
public class SignInAsycTask extends AsyncTask<RequestParams, Void, String> {
#Override
protected String doInBackground(RequestParams... params) {
return new HttpManager().sendUserData(params[0]);
}
#Override
protected void onPostExecute(String result) {
String[] details = parseJsonObject(result);
if (details != null) {
user.setUser_id(Integer.valueOf(details[0]));
user.setName(details[1]);
if (details.length > 2) {
user.setProfilePic(details[2]);
}
setSharedPreferences();
startActivity(new Intent(Signin.this, MainActivity.class));
finish();
} else {
Toast.makeText(Signin.this, "please try again",
Toast.LENGTH_LONG).show();
}
}
}
public String[] parseJsonObject(String result) {
JSONObject obj = null;
try {
obj = new JSONObject(result);
if (obj.has("success")) {
if (obj.getInt("success") == 1) {
if (obj.has("user_pic")) {
return new String[] {
String.valueOf(obj.getInt("user_id")),
obj.getString("user_name"),
obj.getString("user_pic") };
} else {
return new String[] {
String.valueOf(obj.getInt("user_id")),
obj.getString("user_name"), };
}
} else {
return null;
}
} else {
return null;
}
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
here my RequestParams are just a object where I stored all the details like url parameters to send etc and the output of the doinbackground is a String and I am parsing it in my postexecute method

Android AsyncTask change

Why, when I change
private class DownloadTask extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... arg0) {
try {
Downloader.DownloadFromUrl("http://www.sciencemag.org/rss/news.xml", openFileOutput("Sciencemag.xml", Context.MODE_PRIVATE));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result){
mAdapter = new SiteAdapter(MainActivity.this, -1, XmlParser.getSingleItemsFromFile(MainActivity.this));
sitesList.setAdapter(mAdapter);
}
}
to
private void downloadFile(){
try {
Downloader.DownloadFromUrl("http://www.sciencemag.org/rss/news.xml", openFileOutput("Sciencemag.xml", Context.MODE_PRIVATE));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
mAdapter = new SiteAdapter(MainActivity.this, -1, XmlParser.getSingleItemsFromFile(MainActivity.this));
sitesList.setAdapter(mAdapter);
}
i get an error? I just want to call method downloadFile() instead of creating instance of inner class DownloadTask and call execute() of this instance.
The error is telling you that you cannot make network tasks on the main thread.
Look at the Android API where NetworkOnMainThreadException is defined to know more about it.
I hope this helps!
Imagine your method downloadFile() takes too long time - this will block the UI. To prevent this you should use AsyncTask which will do the background operations (downloading your file i guess) and when it is ready will update your UI. In doInBackground() put your downloadFile() method and in onPostExecute() deal with the result. Also be careful what parameters to give to your AsyncTask class.

How can i Handle special kind of exception in doinBackground() method

I am making an android app which requires it to fetch some information from a remote server and therefore i have to make a http request in a async task.Now the problem is that that the response sometimes take more than 2 secs and when it does it give http timeout exception but most of the time it works just fine .So i want to implement the functionality that when i recieve a http timeout exception i want to retry the request again(try the doinBackground again,because network call can only be made in thread other than the main thread) because chances are that it will be successful and all the things that need to be fetched from the remote server will occur in CallRemoteServer() method
Now in my program i have implemented something like this
new AsyncTask<Void, Void, Void>() {
private boolean httpResponseOK = true;
#Override
protected Void doInBackground(Void... params) {
try {
CallRemoteServer();
}
} catch (Exception e) {
httpResponseOK = false;
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
if (httpResponseOK == false) {
//Show an alert dialog stating that unable to coonect
}
else
{
//update UI with the information fetched
}
});
Can someone advice me how can i implement something which i have mentioned above ,i mean that if i get some other exception other than timeout than show an alert dialog otherwise retry atleast five time more CallRemoteServer method before showing the dialog that unable to connect.
I am not able to think of any good way to implement this logic.
Thanks in advance
You're probably getting a ConnectTimeoutException (or check in the logs what is the IOException you're getting). I would first try to extend the timeout. Some similar answers for this can be found here or here.
However, an auto-reconnect mechanism is a must to have. I would implement it using recursive code:
final int maxAttempts = 5;
protected MyServerData callRemoteServer(int attempt) throws IOException {
try {
// do the IO stuff and in case of success return some data
} catch (ConnectTimeoutException ex) {
if(attempt == maxAttempts) {
return callRemoteServer(attempt + 1);
} else {
throw ex;
}
}
}
Your doInBackground method should look like:
#Override
protected Void doInBackground(Void... params) {
try {
callRemoteServer(0);
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
In this way if the connection timeouts it will attempt to retry for 5 max times (you can set the max attempts to anything you like). Just make sure to return some data from this IO operation as that is the most valuable asset from that method anyway ...
For this reason I would change it to following:
private class MyAsynckTask extends AsyncTask<Void, Void, MyServerData> {
#Override
protected MyServerData doInBackground(Void... params) {
try {
return callRemoteServer(0);
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(MyServerData result) {
if(result != null) {
// display data on UI
}
}
}

How to close parent thread on Android

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>
//...
}

AsyncTask not stopping while loading images.

This is my AsyncTask, called from getView of an adapter:
class LoadImage extends AsyncTask<Object,Void,String>{
private ImageView imv;
private String path;
public LoadImage(ImageView imv) {
this.imv = imv;
}
Bitmap userAvatarStream = null ;
Bitmap IconStream = null;
URL IconURL;
ProgressDialog dialog;
#Override
protected void onPreExecute(){
//Setting all the variables by getting the ids from the layout
return;
}
#Override
protected String doInBackground(Object... params) {
try {
IconURL = new URL(cr.ImageUrl);
IconStream = BitmapFactory.decodeStream(IconURL.openConnection().getInputStream());
}
catch (MalformedURLException e){
e.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String result){
// ImageView user_avatar = (ImageView)v.findViewById(R.id.follower_user_avatar);
imv.setImageBitmap(IconStream);
return;
}
The problem that I get here is that the images keep loading. Lets say I scroll down and the images go away to be refreshed again if I scroll up the list. It keeps making calls to get the images. This behaviour is obviously undesirable except at one place that if the internet on your cell-phone goes down and comes up again, this would help to auto-load the images. But, in the current state even that is crashing as it keeps making calls. How to stop AsyncTask from doing that?
Just cache you images to filesystem or memory.
Each time you scroll the list getView is called. If you put the image loading method on getView and didn't use Image Caching then it'll download the images again and again. There are some opensource image loader for list with caching support.
One of them is droidFu. It supports two level of caching. Filesystem and memory. Get droidFu from following link.
https://github.com/kaeppler/droid-fu
Try a boolean flag to keep the check whether the image was loaded successfully or not.
If it was not then only make a call to Load Image Asynctask.
You may need to use a boolean array to keep the track if there are more than one row in adapter.
Try this code:
class performBackgroundTask extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog.setMessage("Please wait ...");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
#Override
protected String doInBackground(String... arg0) {
callxmlparser();
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (ringtoneNamelist != null && ringtoneNamelist.size() > 0) {
songslist.setAdapter(new Songslist());
} else {
Toast.makeText(SongsList.this,"Network signal speed is too slow\ncannot parse the data from the server\n Please try again", Toast.LENGTH_LONG).show();
}
dialog.dismiss();
}
}

Categories

Resources