Where should AsyncTask be? - android

I am new to android programming. I would like to get some advices about AsyncTask. I have created a main activity and one fragment in which i will display content. The use for AsyncTask in my program is to download data from internet. So, the question would be: where it should be? In the fragment's class or activity's?

You have three choices:
You can make it an inner class inside of the Fragment. This is probably OK if this asynchronous task is only specific to the fragment and you won't ever reuse it
You can make it an inner class inside of the Activity. The is better if you have one activity that controls many Fragments that may reuse the same asynchronous task.
You can make it a class of its own if you plan to reuse it in man places in your application or even if you just want it neater. If you do plan on reusing it but the places that are reusing it may need some slight differences, then you might want to abstract it to make it flexible.
Hope that helps.

Related

Activity without UI to write a maintainable code

What is the use of Activity without UI? I have a MainActivity where I feel the code is too long and I was thinking about possibly creating a separate Activity without UI for each task and call it in my Main Activity (or use a Headless Fragment maybe?) in order to keep my code maintainable. Is that a bad approach? How do you manage relatively long code in one Activity?
That's a bad idea. It makes sense to break an activity up into multiple classes if its too large/too complicated. If those pieces have a UI, that's basically a fragment. If they don't, they should be some other class. But there's no reason to make them Activities- they're just classes.
THere's very few places where it makes sense to have a headless Activity. Almost all of those places are where Android requires you to start a context but you're not sure which one to start up yet (for example a headless activity that does url routing that's too complex to put into the manifest).
There a lot of things wrong with your questions.
First... An Activity without UI, then doestn need to be an Activity.
Second, you must know what is a class and why we use classs.
Third, When you have long code, maybe your logic is bad, you can separate en in other class the code, example: Adapters, Helpers, Task, etc.... the same activity and code must give you and idea how separte correctly if you know the concepts, please, maybe if you post the code we can help you more.

Android Model-View-Presenter(MVP) How to Return Long-Running AsyncTask

I am somewhat new to Android, and I am writing an app. I am getting to the point where I am starting to more thoroughly test my code, and therefore, I would like to implement the MVP design strategy since it adds more testable layers to the code. One of the supposed benefits of using MVP that I can not seem to understand is how it helps with running AsyncTasks as they are performed dynamically. Since you want to avoid any Android specific components in your Presenter class, how are you supposed to reference the Activity that utilizes the AsyncTasks? Tutorials about MVP show the Presenter object having methods that take in an Activity as a parameter and return to it; however, if your AsyncTask takes a long time and your Activity has been destroyed through something such as rotation change, how do you return to the proper Activity? I currently store my AsyncTask in a Fragment so that it is saved on Orientation Change. I am having a hard time finding a workaround that implements the MVP practice.
To answer your question, there isn't much you can do to avoid passing Android classes to your Presenter class. But instead of passing the Android object as a parameter, add a method to your View class that returns it (e.g. getActivity()).
That said, I strongly suggest you use a Loader instead of an AsyncTask. Loaders were designed specifically for your use-case. They can also run in the background but their lifecycle is tied to the lifecycle of an Activity or Fragment.
If you switch to Loaders, add a method like getLoaderManager() to your View interface.
If I dont miss-understand your question, your are trying to use retained non-UI fragment for long-runing task, right?
Here is my suggestions in your case:
Make ActivityView interface for your Activity
Using WeakReference<ActivityView> to refer your activity inside your Fragment Presenter (to avoid memory leak issue)
When Activity re-created, try to get your retained fragment and reset your Fragment Presenter's ActivityView. You can look at this Google Example to know how to deal with loading data while configuration changed.
In conclusion, just use WeakReference to avoid memory leak issue, and try to re-set your Presenter'sview when activity is recreated

Android SoftReference To Custom class Containing an AyncTask

I've just started to use SoftReference in my Fragment implementation, which sets setRetainInstance to True, and I have a question concerning..
Overview:
What I'm doing is creating a list of soft references in order to be able to have more than one AsyncTask running and still keep references.
BUT, my list keeps references to custom class objects which wrap an AsyncTask but not one themselves.
Question:
Will the behavior of SoftReference stay the same?
Will Android still "couple" my fragment and all those AsyncTask, or am I missing the
whole idea by doing this?
Code Example:
public class myFragment extends Fragment{
List<SoftReference<MyClass>> myList;
...
}
public class MyClass{
private AsyncTask task;
...
}
Edit: I changed the question to a SoftReference question after NKN's comment about WeakReference being "too weak". Thx for that..
The question still remains though:)
If I understood your idea correctly, you want to have an array of AsyncTask instances which you control. In that case, as they probably are enough critical data to store them into that SoftReference and endangering their content because of the Garbage Collector, I'd personally change the SoftReference approach to get advantage of the AsyncTask structure.
I'd declare that ArrayList but directly of MyClass instances (not SoftReferences). You can implement a method in your MyClass class like setTaskId(int), and before executing any task, you would call it with, e.g., the index in your ArrayList of that instance.
You'd then call the execute() method, and once you've terminated processing that AsyncTask, the onPostExecute() method would be called, from which you'd call a method within your Fragment to say this instance of AsyncTask has already ended, and you could simply use yourArrayList.delete(on_that_id).
In your question you mention you do this to have several AsyncTasks. You may hay as much as you want, but read this before doing it because the execute() method of AsyncTask has suffered drastical changes within version changes and you might need to adequate your code to them.
--- EDIT ---
Using AsyncTasks within Fragments has an additional complication, by the time an AsyncTask finished, precisely as you comment, it might have been detached. So you'll have to implement additional logic mechanisms to check whether it is attached via isDetached(). Keep also in mind that isDetached() only works if you detached your Fragment explicitly, otherwise you'll need isAdded().
You don't need to use it all the time, just keep in mind Fragment lifecycles and call it whenever you'd need to make an action that involves Fragments being attached and so.
To simplify it a little, you could move the AsyncTask initialization and logic to the parent activity, so if a Fragment is detached it may act properly (like, e.g., discarding the results if the fragment is no longer attached, or whatever you need).

Code Repetition Confusion

In my Android Application, I have two activities.
One Activity lets the user take a picture. This picture is saved, and then uploaded to the server. The server returns some info and displays it in a list.
The other Activity is a gallery. The user can select a picture, upload it and get the same info in a list (the same as the first activity)
The way I've implemented is this:
upload and Info task is a seperate AsyncTask called WebServiceTask. Both Activities execute this task.
I created a WebServiceTaskInvoker interface so that each activity could specify what happens on preExecute, postExecute, progressUpdate.
The problem is that the two activities pretty much do the exact same thing on preExecute, postExecute and progressUpdate so there's code repetition between the two activities.
OnPreExecute: Both Activities check internet connectivity
OnProgressUpdate: Both Activities change a TextView's text
OnPostExecute: Both Activities create a dynamic ListView and populate
it with results.
How can I fix this?
I know one way would be to combine the two activities into one but form past experience, I've known this to be troublesome and messy.
I could put the UI code in the WebServiceTask but that would lead to tight cohesion.
Implement a base class for the two activities that executes common code. Implement the activities as subclasses of your base class to execute different code.
An alternate to Catherine's suggestion is to create an activity mode enumeration.
Pass this mode as an extra when launching your activity.
If the mode is MODE_GALLERY then load the gallery.xml layout and populate it, if not then load the other layout.
Just make sure that you use the same id's for the common views, an easy way to do this is to use the include tag in your layout files.
The advantage of this is that you only have one activity file instead of three which would be required for the subclassing method.
You may also be able use fragments, but I don't have any experience with these so I can't advise ou further.
One last note, I would avoid putting UI code into a task.

includeed layouts - update in multiple activities

I have an app with multiple activities and multiple layouts. However, one piece of layout is included on several activities. I also have a thread which updates this layout. However, when i switch activity it doesn't work. Since the layout is included the elements have the same ID's, shouldn't it just work? Or do I really need to fetch an object for each element in the layout and feed it into my thread in order to make it update the elements in a new activity?
You should run the update code for each Activity/View, although the XML included is the same, each is a different instance.
My suggestion is on Restart verify is there is any modification to do in each activity, a simple way is to each Activity extend a BaseActivity that has this code.
I include a layout for adverts in my app, but on each activity that uses it, the adverts need to be reloaded.
If I call an activity from one that is using the same included layout when I go back to the previous activity it's still there.
I guess this is what you are seeing....
So you can also save that data inside sharedPreferences (if it is little data and primitive objets or parceable objects).
Also you can extend the Application class and store the data there and update every activity inside the onResume() method. that i believe is the best way to handle this. and this is quite simple to do.
Ask google about extending the application class and he will provide tons of results on how to do it. its an easy way to pass data between activities and/or keep a reference to a single object which you will use throughout the app. Just be carefull to clear it when you wont need it anymore because it will stay in existance untill the application is finished() (which comes with the application extension living thru the whole application lifetime).

Categories

Resources