Passing a activity context into a static method, memory leak potential? - android

I've seen this particular technique for launching activities and it seems to me like a bad idea because of static contexts but I was hoping someone might have a legit reason behind this approach.
The activity you want to launch implements a static launch(Context context) method that sets up the intent, flags, etc and finally starts the activity.
public static void launch(Context context){
Intent i = new Intent(context, SomeOtherActivity.class);
// flag stuff
context.startActivity(i);
}
Then a DifferentActivity could go and launch SomeOtherActivity with one line.
SomeOtherActivity.launch(DifferentActivity.this);
I like how it allows you to setup the flags in the activity away from the DifferentActivity that is launching it but it doesnt seem like a good enough reason to rationalize passing that activity's context into a static method.
Wouldn't this cause DifferentActivity to not be garbage collected because now that static method has a reference to it? This seems like a memory leak to me and probably not a good idea to do just to be able to keep the flags contained in the activity that is being created.
Is there something I'm missing here that makes this a good practice to do?

Passing something into a static function isn't a potential memory leak. Storing a variable in a static variable is. This technique is perfectly safe. Its one I'd even recommend, as you can pass in variables to the function and store them in extras inside the class that is going to use those extras, reducing the number of places that need to know of their existence and how they're laid out

Related

Is passing an activity or fragment into static method bad

If I have a method like below:
public static void doSomething(Activity aActivity){
//do Something With The Activity
}
Is passing an activity/fragment into a static method a bad idea in terms of memory usage? Could using this method keep a reference to any method alive for the lifetime of the application?
If I have something like this:
public static void doSomething(View aView){
//do Something With The View
}
Would this keep the reference to the view alive for the lifetime of the application?
Would these 2 examples, if used enough, cause memory leaks or OOM issues?
There is nothing wrong with passing Activity or Context as a parameter to a static method. As long as you do not store a reference to the Activity or Context in a static variable there is no memory leak!
Even if you do store a reference in a static variable, this would be a small memory leak, because the next call to the method would overwrite the reference, freeing the previously stored object for potential garbage collection. So there is no chance of a situation where gradually over time all the available memory would be consumed.
Calling a static method and passing it an argument does not create memory leaks.
It is bad practice (as D. Wasser and everyone else tell you) in general to store an Activity / Context / View into a static variable, but:
You can store static variables even from a member method
Android Studio would raise a warning anyway.
Avoid that, and you'll be fine.
Also, from the Android docs:
If you don't need to access an object's fields, make your method static. Invocations will be about 15%-20% faster. It's also good practice, because you can tell from the method signature that calling the method can't alter the object's state.
If you do have a static method that you use to customize (let's say) you Views, I would consider sub-classing the given View and specify it's behavior as a private member function.
Passing something into a static function isn't a potential memory leak. Storing a variable in a static variable is. This technique is perfectly safe. Its one I'd even recommend, as you can pass in variables to the function and store them in extras inside the class that is going to use those extras, reducing the number of places that need to know of their existence and how they're laid out.
From
Passing a activity context into a static method, memory leak potential?

Saving a static Context variable in Application class

I've wondering if it's okay to do this: whenever we pass a Context variable around, could we just get a singleton reference from the Application class instead
For example here is a subclass of Application class with a single static variable pointing to its own instance
public class App extends Application {
public static mApp;
#Override
public void onCreate(){
mApp = this;
}
}
Then when we need to pass a Context to a method from somewhere, can we just do
foo(App.mApp);
Isn't it okay to treat Context as an application variable?
Well it depends on the context in which you are using it. Many times a context is meant to keep hold of things until it's lifescope is complete and then allow garbage collection to take back whatever it was owning.
Other times the context needs to be an activity to handle life cycle call backs such as onNewIntent or onActivityResult.
Keeping a static instance in the parent is just a shortcut to avoid having to getApplication() and cast it as your type of application. I typically make a method for MyApplication.getApplication().doSomething which will return it's own reference of itself as opposed to ((MyApplication)getApplication()).doSomething
Just seems cleaner for coding purposes. But I would be very leary of using the application context everywhere you need a context, it will come back to bite you eventually.
But yes you can certainly store yourself as a static variable to be shared, I do it in most applications, but typically for a specific shortcut purpose of clean maintainable code, not for cheating on getting context from various crevices.

Alternative to a global variable for passing objects between activities

I need to pass a list of objects between activities, I am using a public static global variable in my Application class.
The problem is that this variable seems to be the first to be destroyed when the activity goes in the background for a while.
I never have problems with the activity going in the background but whenever I use a global variable like this, it always the first gets garbage collected or something to fee memory. This causes my application to crash.
How can I prevent this happening?
This is a bad approach of doing it storing it in a global variable.
You should either serialize your class or create a Singleton pattern and store that object in it.
Serializable Approach
public class ClassIntanceOne implements Serializable{
}
//In Activity
ClassIntanceOne class_instance_one = new ClassIntanceOne();
Bundle bundle = new Bundle();
bundle.putSerializable("object1", class_instance_one);
intent.putExtras(bundle);
startActivity(/*Your class*/);
The easiest solution is to include the objects in the intent, that is starting the other activity. This requires, that your objects implement Parcelable or Serializable.
Then just call:
Intent intent = getIntent();
intent.putExtra("myobjects", listOfObjects);
getContext().startActivity(intent);
It is bad practice in android to make use of globel static variables. The GC will always remove them when your activity goes to the background as the value is not used anymore. Also don't try to keep your object longer in memory as you need it. This may cause poor performance on devices with less memory.
Like SME_Dev said, you will need to serialzie your objects and pass them as an intent extra to the activitys.
When you can searialize your objects it's also easier to restore the current state of the app if it get's destroyed because you can make use of the recreating mechanism in android.

Static Utility class with Context/Activity - Android

Over the development of an Android app I've come to a collection of utility-type methods that I have put into a static class. All these methods are used across multiple Activities and most of them do not require any information from the calling Activity.
However, I now have some methods that require the Context of the Activity and one that requires the Activity itself. Let me exemplify some of them:
getDeviceNaturalOrientation() - Uses an Activity's
getWindow().getWindowManager().getDefaultDisplay() to access the
displays rotation, width, and height to determine the device's
natural orientation.
getDeviceOrientation() - Similar to the above but to get the current
orientation
createFile() - Uses the Context to to access some resources (strings) and to
create and show some Toasts
Now, my big questions regarding this Utils class are:
So far, each function takes a Context parameter which I pass from whatever Activity I'm on, but would it be OK to create a static Context or Activity variable in the Utils class and set it at the beginning of each Activity (like in onCreate)? This variable would be used in whatever functions require a Context or Activity instance.
Assuming the above is not recommended, is it OK to pass an Activity parameter to a method or is there a reason to only pass an Activity as Context? The methods I use for the device orientation functions above are specific to Activity objects, not Context, so either I pass as Activity or pass as Context and cast into Activity (the latter sounding like a terrible idea).
Also, I am very open to the idea that this Util class may not be the way to go for these methods that require Context/Activity, so I would welcome alternatives that would still prevent having copies of these methods in each activity class that uses them.
1)A static link to a context is likely to cause a memory leak. It means that a reference to the Activity will be kept around in the static variable even after its destroyed, so all of the memory of the activity and all its views will remain valid and not be cleaned by gc. You can do this, but you have to be careful to null out the variable when done. Its better just to avoid it.
2)Its a little bit awkward to pass the activity as an Activity, but no technical reason not to. At that point we're arguing over code cleanliness/maintainability. And there are times where the non-clean solution is just easier. Of course in the cases above I'd rather pass the orientation/display/Resources objects to the function than pass the entire context or make special accessors.
I think following design should be fine when you call from Activity
MyUtility utility=new MyUtility();
utility.getDeviceNaturalOrientation(this);
utility.getFile(this);
And you can define these function like
public int getDeviceNaturalOrientation(Activity activity){
//code
return some_oreientation
}
and like this
public File getFile(Context context){
//code
//return file handler
}
Activity is the subclass of Context so you can even change the design to following
MyUtility utility=new MyUtility(this); //this refer to Activity
utility.getDeviceNaturalOrientation();
utility.getFile();
As long as you pass activity you are fine but if you do following from your activity you will get error from first method call
MyUtility utility=new MyUtility(getApplicationContext());
utility.getDeviceNaturalOrientation(); //will throw exception
utility.getFile();
And, yes first idea is not a recommended way.
I would suggest you to send a WeakReference of your Activity or getApplicationContext() (for those works which can work using it) and don't use static method because it cause memory leaks. Read Developer blog also

Is passing context through a static class efficient way or not?

In android, I need reference "context" or to say pass "context" to several classes. For this purpose I have implemented a static class which holds the "context" and all other class access context through it.
//let's say I have a static class DataHolder
//and my main acitivity i.e. whose context need to be refrenced
public class DataHolder{
public static Context context;
}
public class MainActivity extends Activity{
public void onCreate(Bundle bundle){
DataHolder.context = getApplicationContext();
}
}
So, is this process ok to be implemented or it is not the right way to reference in Android application.
The issue here is not about efficiency, but about the inherent risks of storing your context statically.
The context can change in many events, the most likely one is changing the device orientation, so you shouldn't relay on it always. I think you should pass the Context in the constructor to each class you think would use it (or, rather, redesign your code so you don't need it where it's not available, although this may be a bit tricky).
In the worst case scenario, you should try to update it as frequently as you can. But, then again, what's the point in having it always accessible? I think the risks are not worth the laziness (sorry if it sounds rude, I don't mean it to) of making a careful app design.
You should definetely avoid it, since it may lead to a memory leak.
Read: Avoiding memory leaks
This means that views have a reference to the entire activity and therefore to anything your activity is holding onto; usually the entire View hierarchy and all its resources. Therefore, if you leak the Context ("leak" meaning you keep a reference to it thus preventing the GC from collecting it), you leak a lot of memory. Leaking an entire activity can be really easy if you're not careful

Categories

Resources