Will this cause memory leaks? - android

Will the following code cause a memory leak? Essentially I switch between various layouts in my application using setContentView(), and I have member variables of my activity that maintain references to various views (buttons/textviews...) on the layouts.
Am I correct in thinking that if the activity class has a reference to a button and then changes layouts the layout wont be garbage collected because it will still hold a button reference? If this is the case, can I just null the button variable before changing layouts?
Thanks.
public class MyApp extends Activity {
private Button startBtn;
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Set main layout
setContentView(R.layout.main);
startBtn = (Button) findViewById(R.id.startBtn);
startBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
doStart();
}
});
}
private void doStart()
{
// Change to starting screen layout
setContentView(R.layout.begin);
/// .. Work with more views here and change layouts in a bit .. //
}
}

You will want to set the button to null before changing any layouts.

I don't believe that should cause a memory leak. Changing the layout doesn't destroy the activity, so the activity still has control over the bound references. Once the activity is destroyed, all the memory should be cleared up. Also, you might want to think about using separate activities if you're switching layouts that much.

Views of R.layout.main (that you initialy assign in OnCreate) will not become garbage as long as you hold startBtn reference OR as long as your activity's instance is alive. Either way it doesn't look like a potential memory leak. Just make sure to release references to views when setting new layout. Yet another thing to consider is to use WeakReference to wrap references to views of your layout (that's for complex designs). This way, as soon as your layout is no longer attached to activity (no strong references to views), all views can become a garbege even though you are referencing them via WeakReference.

Related

code reusability in android

I have 3 activities with the same toolbar. I would like to avoid copying code on each activity. I know I can use <include> tags in every layout in order to reuse the same layout for the toolbar. Now I would like to share the event handlers for each button of the toolbar in all the activities. I am thinking of making a toolbarActivity which extends Activity class and the 3 activities extends toolbarActivity, so in onCreate method, when I call base.OnCreate, all the event handlers would be defined. But, SetContentLayout was not called yet, so base.OnCreate will not find the buttons. Remember the 3 activities have different layouts. Do you know the best way to reuse code in order to avoid copying all the event handlers in OnCreate method for every activity and allowing me to override some functionality?
Android is used on mobile devices so at development time their is no way to know the size and dimensions of the users device. On large devices many UI elements can fit. On smaller devices few UI elements can fit. Your question relates to this dilemma and therefore has many possible answers. Logically for code to work it must exist inside the source, ie you could cut and paste, a bad solution because you end up with many versions of this "same" toolbar or you could refer/reference one "external" toolbar. Fragments come to mind as does having a separate source file. UI source files can be thought of as pairs. Java for dynamic elements and xml for static. So in summary just reference an external fragment that has implemented your toolbar.
If you keep the naming conventions for the buttons and other things in each layout that are tied to the references in your activities then you should have no problem.
For example if you have a '#+id/login_button' in one layout then just use the same convention for the same type of button in the next one and youll be fine.
You could define a base activity which all your other activities extend, and make it implement a click listener (or whatever interface you are using to listen for button presses). You can check the Id of the clicked view and thus provide a callback to perform whatever logic you want.
public class BaseActivity extends Activity implements OnClickListener {
public void onCreate() {
myBtn.setOnClickListener(this);
}
public void onClick(View v) {
if (R.id.my_btn == v.getId()) {
onFoo();
}
}
protected void onFoo() {
// TODO handle foo
}
}
You can then override the method in your subclasses if you need to provide different behaviour.
public class DifferentActivity extends BaseActivity {
#Override protected void onFoo() {
super.onFoo()
// TODO handle foo differently
}
}

Should I delete the OnClickListener in onDestroyView?

I set listener for my button:
View onCreateView(...) {
...
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//some work
}
});
...
}
If I use ButterKnife, it is recommended to call ButterKnife.unbind(this) in onDestroyView(){..}. Do I need to remove the listeners for avoid memory leak?
void onDestroyView() {
...
btn.setOnClickListener(null)
}
It depends...
Do you have different layouts for portrait and landscape, and you have it configured so that when you rotate only the view is destroyed?
If so, YES to prevent references of an unused view on a used Activity/Fragment (that could prevent it from being GC)
If when you rotate the view and Fragment/Activity is destroyed, then NO you don't need to do it, the GC will take care of it.
This difference exists due to the fact that Android uses a Mark-Sweep algorithm on it's GC which will prevent the cases where 2 unused objects with references to each other (circular references) from being collected... but not the cases where a used object has a referenced to an unused one.
Some useful Q&A about this:
Does setting Java objects to null do anything anymore?
Android: Is there any advantage of settings references to null when an Activity is being destroyed?
Technical details of Android Garbage Collector
How does garbage collection work in Android 4.2 Jelly Bean Dalvik?

Android - Class variable vs method variable for Views

Which way is better programming for memory management when dealing with Android Views? I believe the second way is better because the TextView is only accessed when needed and then, hopefully, garbage collected. Would love to hear your views!
public class MainActivity extends Activity {
TextView tvHelp;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvHelp = (TextView) layout.findViewById(R.id.ivHelp);
tvHelp.setText("Started");
}
#Override
public void onResume() {
super.onResume();
tvHelp.setText("Resumed");
}
}
Or this
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tvHelp = (TextView) findViewById(R.id.ivHelp);
tvHelp.setText("Started");
}
#Override
public void onResume() {
super.onResume();
TextView tvHelp = (TextView) findViewById(R.id.ivHelp);
tvHelp.setText("Resumed");
}
}
It doesn't make that much difference. The first one will help you avoid multiple calls of findViewById() which is CPU consuming. The second one will help you preserve some bytes on the heap. But by doing this you will also create unreferenced objects which will stack on the heap until the GC passes (which is CPU consuming). GC will also starts when the memory is running out (when you create unreferenced objects for example). So the first solution is definitely the best one to use.
You'll avoid:
Code repetition
Multiples calls to findViewById
Unreferenced objects which will stack in the heap until the GC passes
In your case, it won't really make any difference as far as memory consumption. The Activity is going to hold a reference to that view through its hierarchy until it's destroyed whether you keep a reference to it or not. Releasing your reference to it won't make it be garbage collected.
Once the Activity goes through onDestroy(), it and its view hierarchy will be garbage collected anyway, so for this case I wouldn't worry about the difference.
One case where this can make a difference is in Fragments where the View lifecycle differs from the component lifecycle. Holding a reference to a View from onCreateView() or onViewCreated() can temporarily cause additional memory usage once they go on the backstack. You can release the references in onDestroyView() since they won't be valid anyway -- unless you are keeping the whole view hierarchy around manually.
For more info: https://stackoverflow.com/a/26370042/321697

Android app best layout for image buttons?

I'm developing a VERY SIMPLE android application that is designed with 5 activites, each with its own RelativeLayout.
1) The Parent (or Home)
2-5) Children of Home which each have their own back buttons, which call finish().
The Problem:
I'm using image assets everywhere and I have stress tested the application by constantly switching from Parent to Child over and over. I RUN OUT OF MEMORY due to the age-old "VM budget exceeded" error.!
What I have tried:
I have tried trimming down the image assets set most of my objects to static references so that they be garbage collected when the Child activity finishes.
I have installed the MAT tool to examine the HPROFS dumps, which was very confusing.
I have read about SoftReferences or WeakReferences and File caching techniques, but have yet to implement them.
EDITED...here's my onDestroy for each child activity.
#Override
protected void onDestroy() {
super.onDestroy();
// unbind all drawables starting from the first viewgroup
unbindDrawables(findViewById(R.id.info_layout));
c2 = null;
runnable = null;
mFont = null;
root = null;
myThread = null;
myImage = null;
v = null;
txtCurrentTime = null;
common = null;
System.gc();
Log.e("Info", "Info destroyed.");
}
ALSO...All of these are declared as private at the start of the class declaration. Do they need to be declared as static or something else?
The question:
Is there a different type of layout I could use that wouldnt involve calling finish() on the activities, like TabHost or ViewFlipper something similar...that would prevent me from having to start a new activity and finish it
OR Perhaps...a way that when I call finish() on my Child activities so that everything gets garbage collected?
XML and/or code examples are welcome.
I am open to either, or any other way that could be suggested.
Thanks.
Rick
If you're running OOM after switching from parent to child repeatedly then you're probably leaking the child activity. I'd run an hprof and make sure that you aren't accumulating child activites, and if you are try to find out what references aren't be freed and make sure they go to null in onDestroy.
This usually happens when the framework has a pointer to your child context that it doesn't get told to release via an unregister, or through a circular reference of some sort in your app, possibly through non-static child classes.

Difference between making a button implementation in class or a final inside the onCreate()?

So usually in guides when making a holder for a View let's say Button, I usually see it on the onCreate method like this:
public class className extends Activiy{
public void onCreate(){
final Button button = (Button) findViewById(r.something.something);
}
}
Well I was wondering if there's any difference and if ever there is, which is a better in approach from that one to this one:
public class className extends Activiy{
Button button;
public void onCreate(){
button= (Button) findViewById();
}
}
The first creates a method local variable, the second creates a field in each instance of your Activity class.
It is always better to use the smalles (that is most local) scope possible. On Android the memory usage makes this even more important. Therefore please go with the first solution (assuming that you do not need to reference that button from multiple other places in your code).
If you declare it the first way, it will be available only inside onCreate() method.
If you declare it the second way, it will be available all around the activity.
Use the first way, if you do not need to use the button outside onCreate().
I do not see any other difference.

Categories

Resources