Are there any performance (or other) concerns on passing Activity as a method parameter? I need to define an image picker/cropper in a modular way (UtilClass) that can be used in several activities and I will need to make Activity-dependent calls.
Well there is no performance concern, since you will pass the memory address.
Take a look at this post please:
Is Android Context thread safe?
You should avoid keeping reference to activity after it closed, I see two ways: using WeakReference in Utility class or set activity reference to null in Utility class in onDestroy \ onPause method.
Related
I've looked around but never found a straightforward answer to this question. I'm wondering what would happen if I use a pattern that requires me to pass a Context to static methods to do things on the backend. For instance:
public static Observable<CreateThing> createNewThing(String thingName, Context context) { // Passing Context in
return RestNetworker.handleResponse(ServiceGenerator.createService(Service.class).createThing(thingName))
.doOnNext(response -> DatabaseHelper.getInstance(context).createThing(new Thing(response.getThingId(), thingName))); // context used to get instance of DatabaseHelper
}
This method makes an API call and then writes the object to the database locally after a success response. However, I need to pass a Context to create the instance of the database helper. I could alternatively pass the database helper itself, but then I'd be creating the instance (rather getting it, since it's singleton) in the Activity code and I'd rather not do that either.
My question really is: If, say, a user exits the Activity while the API call is in progress, will this Context instance get GC'd and result in an NPE when the response comes back? I've done this kind of thing before and never noticed that issue, but it really seems that there should be some consequence of doing this. I know that other developers must do some things off the UI thread that require a Context, so this should be a relatively easy question to answer.
Thanks guys! Please let me know if you need any more information to provide better context. Heh.
The rule is that you do not pass an instance of the Activity to some object that may keep a reference to it outside of the lifecycle of the Activity. This will cause a memory leak, as the GC will not be able to free the memory allocated to the Activity and the entire view tree contained within. In those instances you pass getApplicationContext().
In cases where the context will only be referenced for the duration of the method call, passing the Activity as this is fine.
In your case, it seems like DatabaseHelper may store a reference to the context, so I would use getApplicationContext() Note that you would not get NPE because the reference was GC if you passed an Activity, that doesn't make sense - if the DatabaseHelper was storing a strong reference, this could not occur (at least on the reference to the Activity itself).
I'm calling ActivityCompat.requestPermissions in order to get permissions under android M, however, this requires an activity in the argument. This would be fine, except that I want to call it from a singleton, and the singleton can be used by any activity in the app.
ActivityCompat.requestPermissions(context, PERMISSIONS_LOCATION, REQUEST_LOCATION);
I want to avoid holding a reference to any activity within the singleton as that's a surefire recipe for a memory leak, and also I'd prefer that the singleton not hold an activity at all because it requires useless code in all the activities that call (every single one of them is going to have to include an extra argument in the getInstance() in order for the singleton to hold an activity - the singleton needs to get the activity from somewhere).
Now, I can technically get an activity and then set it to null straight after I request the permission, however that still leaves me with tons of useless activity arguments in every single activity where I make a call to the singleton. Is there a more elegant solution to this problem that I'm just not seeing?
The documentation on requestPermissions says that the activity parameter is the target activity where you want to show the pop up if you haven't included the permission in your manifest and for this purpose that method requires you to pass an activity and not the context, because upon finish the request permissions task it will then return a result to the calling activity(that is the activity passed as the parameter to the method). If you are so adamant about implementing this through your singleton I suggest you create a function that accepts the activity in the parameter and the callbacks too as you WILL need to handle the callbacks if the permissions were given or not
I have a few Activities that use the exact same methods logout() and redirect() multiple times.
Would it be alright to use a separate class and mark these methods as static as follows:
public class AuthUtil {
public static void redirect(SessionManager manager, Activity activity) {
manager.redirect();
activity.finish();
}
public static void logout(SessionManager manager, Activity activity) {
manager.logoutUser();
activity.finish();
}
}
And call them from the activity by:
AuthUtil.logout(mSession,this);
Or should I be extending the Activities that use the method to a common Activity class and just put the methods there (except without the parameters since the methods wouldn't need them in that case)? However, I won't be able to do this if one of the activities extends FragmentActivity, another ActionBarActivity, which is actually the case for me...
Basically, I want to know if it's bad practice to call the activity's methods like that from a separate class body than its own? If so, what should I be doing?
No it is not considered bad practice - but choosing that route because it is easiest may well be a decision you later regret.
You should ask yourself the following questions:
Who is responsible for finishing the activity?.
Who knows when to finish the activity?.
Who knows how to finish the activity? (usually the Activity but be certain).
In your case it could be:
The activity itself
The session manager
The algorithm
Something else entirely
Once you have answered those questions you should have a good idea how to implement.
Remember that you could also create a third object, perhaps an ActivityManager that takes responsibility. It could hold a list of activities that need to be finished when the SessionManagercompletes the session. You may then have:
sessionManager.redirect(activityManager);
other scenarios could result in
// Make sure when the session completes this activity is finished.
sessionManager.registerAttachedActivity(Activity activity);
or
// Activity must finish when redirect completes.
activity.finish(sessionManager.redirect());
It really isn't as simple as good practice and bad practice it's more about doing it right.
Would it be alright to use a separate class and mark these methods as
static as follows
No. It would make very difficult to figure out where are the activities being finished by looking only at the source code of a given activity. And its also hard to see in what thread are those methods running for instance. And finally, because they are static, you'll have to add a new method if an activity needed to perform additional or different actions when redirecting or logging out.
Or should I be extending the Activities...
In my experience it is not a good idea to tie activities to an inheritance hierarchy, and you named a few good reasons for not doing so. If you need code reuse try to use composition instead.
I'd always call Activity.finish from the very same activity, in fact I'd like to have the whole lifecycle picture contained in the activity's code. But this is just what my guts tell me, there's no definitive correct answer to your question.
this might not be a new question to you - I have my main activity and I would like to call a method in another activity. Now if I do this I get my application not responding and closed.
I hear there is some special way to call methods in other activity classes?
This is generally a bad idea, the reason why is because you have no control of the life-cycle of an activity that is not the active Activity. You could call a method and find that the activity you are calling has been destroyed to reclaim resources.
A better option would be to create a Utility class that can provide functions to multiple activities, or place things that must remain throughout the life-cycle of your application into the application class, or shared preferences.
If all your trying to do is pass information to a new activity or get information from another one, you may want to package that information into the intent, or again place it in shared preferences.
Just create another class and place that method in that class.Then access from both activity.
I understand that Android Activities have specific lifecycles and that onCreate should be overridden and used for initialization, but what exactly happens in the constructor? Are there any cases when you could/should override the Activity constructor as well, or should you never touch it?
I'm assuming that the constructor should never be used because references to Activities aren't cleaned up entirely (thus hampering the garbage collector) and that onDestroy is there for that purpose. Is this correct?
I can't think of any good reason to do anything in the constructor. You never construct an activity directly, so you can't use it to pass in parameters. Generally, just do things in onCreate.
A good reason for putting things in the constructor as Gili's comment had stated is the use of final fields.
However, if you initialize things in the constructor, then the lifespan of the object will be a little bit longer, though I don't think by much because the onCreate would be called shortly thereafter.
Although it's against my ideal, I do avoid the constructor for initialization of the activity members and rely on onResume() and onPause() for resources that my app is dealing with.
For onCreate() I usually use it to do view mapping to local variables. Though android-annotations already does that for me so I rarely have an onCreate() method for my Activity. I still use it in Service though.
However, if you look at the members you may be initializing
they would have a "close" method that you have to invoke at the proper time (onResume or onPause)
they would be part of the view which means it needs to be initialized then onCreate needs to be called
they are constants which don't need to be put in the constructor anyway, just a static final would do. This includes Paint and Path constants which can be initialized by a static block
I am now on a case that needs to override the constructor. In fact, I have some activities that have the same structure. So instead of creating many activities, I'll create one "Master" activity and the others will inherit this one. So I need to override the constructor of the child activity to be able to initialize some variables that will be used in the oncreate methods.
In two words, the constructor makes you simulate a "masteractivity" that can be reused by inheritance!
You need to override the Constructor when your activity will have custom params or you want to track calls from classes that inherited from.