Memory management and GC

Under eye of Garbage Collection Management objects are classified to 4 reference  degrees or strength: 

strong, soft, weak, Phantom ( in order from strongest to weakest)

strong are those references are alive and not supposed to be garbaged , for example when currently your working on sb as

StringBuffer sb = new StringBuffer()

soft have less priority to be garabged than weak

Phantoms are supposed dead and phisically removed from memory calling get() return null all time, it will be enqueu quickly in ReferenceQueue (The ReferenceQueue class makes it easy to keep track of dead references)


Soft Reference is helpful while you want to cache images to avoid time frame that consume in loading from Disk every time ,SoftReference will be garbaged as late as possible  take a look here to cache images which one is better  

HashMap<String, WeakReference<Bitmap>> cache = new HashMap<String, WeakReference<Bitmap>>();

HashMap<String, SoftReference<Bitmap>> cache = new HashMap<String, SoftReference<Bitmap>>();


softrefernce is better than week for a cache because they are more available and get will return null with less probability



Weak and strong references:

WeakReference

WeakHashMap


ReferenceQueue: location to keep traces of dead objects(garbaged)!

*************************

final class cannot be extended

**********************************

where to use weakrefrerences:

suppose this scenario:


public class SampleActivity extends Activity {

 

  private final Handler mLeakyHandler = new Handler() {

    @Override

    public void handleMessage(Message msg) {

      // ...

    }

  }

 

  @Override

  protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

 

    // Post a message and delay its execution for 10 minutes.

    mLeakyHandler.postDelayed(new Runnable() {

      @Override

      public void run() { /* ... */ }

    }, 1000 * 60 * 10);

 

    // Go back to the previous Activity.

    finish();

  }

}



When the activity is finished, the delayed message will continue to live in the main thread's message queue for 10 minutes before it is processed. The message holds a reference to the activity's Handler, and the Handler holds an implicit reference to its outer class (the SampleActivity, in this case). This reference will persist until the message is processed, thus preventing the activity context from being garbage collected and leaking all of the application's resources. Note that the same is true with the anonymous Runnable class on line 15. Non-static instances of anonymous classes hold an implicit reference to their outer class, so the context will be leaked.

To fix the problem, subclass the Handler in a new file or use a static inner class instead. Static inner classes do not hold an implicit reference to their outer class, so the activity will not be leaked. If you need to invoke the outer activity's methods from within the Handler, have the Handler hold a WeakReference to the activity so you don't accidentally leak a context. To fix the memory leak that occurs when we instantiate the anonymous Runnable class, we make the variable a static field of the class (since static instances of anonymous classes do not hold an implicit reference to their outer class):


In Java, non-static inner and anonymous classes hold an implicit reference to their outer class. Static inner classes, on the other hand, do not.


so fixed version is:

public class SampleActivity extends Activity {


  /**

   * Instances of static inner classes do not hold an implicit

   * reference to their outer class.

   */

  private static class MyHandler extends Handler {

    private final WeakReference<SampleActivity> mActivity;


    public MyHandler(SampleActivity activity) {

      mActivity = new WeakReference<SampleActivity>(activity);

    }


    @Override

    public void handleMessage(Message msg) {

      SampleActivity activity = mActivity.get();

      if (activity != null) {

        // ...

      }

    }

  }


  private final MyHandler mHandler = new MyHandler(this);


  /**

   * Instances of anonymous classes do not hold an implicit

   * reference to their outer class when they are "static".

   */

  private static final Runnable sRunnable = new Runnable() {

      @Override

      public void run() { /* ... */ }

  };


  @Override

  protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);


    // Post a message and delay its execution for 10 minutes.

    mHandler.postDelayed(sRunnable, 1000 * 60 * 10);

    

    // Go back to the previous Activity.

    finish();

  }

}



The difference between static and non-static inner classes is subtle, but is something every Android developer should understand. What's the bottom line? Avoid using non-static inner classes in an activity if instances of the inner class could outlive the activity's lifecycle. Instead, prefer static inner classes and hold a weak reference to the activity inside.


using WeakReference, SoftReference for Image Cache processing was an old method back to android 2.2, things now changed

from Android 3 to later , Developer should use LruCache instead;

*****************

Theory note: when subclassing a class A<T1,T2> never declare your class as "class B<T1,T2> extends A<T1,T2>"


but  class B extends A<T1,T2>


Code Optimization

Make a method static if it does not access member variables!!!

Avoid internal getter/setters

use int instead of enum

try use static final for constant

HashMap is heavy if you can replace it by  SparseArray it would be much more efficency

Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.Every class in Java (including anonymous inner classes) uses about 500 bytes of code ,Every class instance has 12-16 bytes of RAM overhead

Be careful with code abstractions .Often, developers use abstractions simply as a "good programming practice," because abstractions can improve code flexibility and maintenance. However, abstractions come at a significant cost: generally they require a fair amount more code that needs to be executed, requiring more time and more RAM for that code to be mapped into memory. So if your abstractions aren't supplying a significant benefit, you should avoid them.


============

In android wh have 4 components:

<activity>, <service>, <receiver>, and <provider>


in manifest they all have a android:process attribute to say in which context its running

The <application> element also supports an android:process attribute, to set a default value that applies to all components.

-------


Each app process is forked from an existing process called Zygote. The Zygote process starts when the system boots and loads common framework code

Memory management: every app is dedicated a Virtual Page Memory which can grow up , but limited to a level by System (Dalvik)and not more!!!!if it reachs a max capacity and require more memory it recive

 OutOfMemoryError,in your app you can verify the size of heap available for you by  int getMemoryClass()

return is integer og megabayte , by setting  largeHeap attribute to your manifest your heap will be latger!

LRU:cache for apps least used

When you start a service, the system prefers to always keep the process for that service running!

so LRU is reduced to less process

he best way to limit the lifespan of your service is to use an IntentService which finishes itself as soon as it's done handling the intent that started it

To be notified when the user exits your UI, implement the onTrimMemory() callback in your Activity classes. You should use this method to listen for the TRIM_MEMORY_UI_HIDDEN level, which indicates your UI is now hidden from view and you should free resources that only your UI uses.


Notice that your app receives the onTrimMemory() callback with TRIM_MEMORY_UI_HIDDEN only when all the UI components of your app process become hidden from the user. This is distinct from the onStop() callback, which is called when an Activity instance becomes hidden, which occurs even when the user moves to another activity in your app. So although you should implement onStop() to release activity resources such as a network connection or to unregister broadcast receivers, you usually should not release your UI resources until you receive onTrimMemory(TRIM_MEMORY_UI_HIDDEN). This ensures that if the user navigates back from another activity in your app, your UI resources are still available to resume the activity quickly.[notice this callback is invoked in addition when system is in Low state)


How system works : it has a list of "importance hierarchy"  

In all cases System start killing process in LRU by priority/privileged, those having a service considered to have more privilege so killed at the end ! a process with no UI more likely will be killed before a process with having UI!!!UI is a considered as a privileged ,the following are the privileg level in order of each components inside process

1)when process hosts :service with UI or foreground having (startForeground())

2)when process hosts : generic service with oncreate onstart..

3) when process hosts :background service

4)when process hosts : a BroadCastReceiver


Empty process are often killed!



Threads:In Android threads are either UI or no UI


NO UI:

new Thread(new Runnable()

    {

        

    public void run()

        {

//cannot access UI

        }

    }).start();




UI threads:


Activity.runOnUiThread(Runnable)

View.post(Runnable)

View.postDelayed(Runnable, long)


simple example:

 new Thread(new Runnable()

    {

        public void run()

        {

            view.post(new Runnable()

            {

                public void run()

                {

                    view.setBackground(R.drawable.xxx);

                }

            });


        }});


but for more control on thread , UI with shake handing function between main UI and threads which is more convenient best way is to use AsyncTask (when need to interact with user)


class DownloadPictures extends AsyncTask<String, Void,List> {



        protected List doInBackground(String ...url) //this method executes on worker thread

        {

//calculation NO UI

            return  list; //returned value will be delivered to onPostExecute

        }

        protected void onPostExecute( Bitmap bitmap)

        {

//UI access

        }

    }



**insert , delete,update... methodes of a ContentProvider executes in a bunch of pool threads in process not UI threads

**Important : when your activity restarts in an unexpected way for any reason and one of enoying one when change in orientation that's an issue  for your worker threads !

***********************************************************


OPTIMIZATION:

Make a method static if it does not access member variables!!!

Avoid internal getter/setters

use int instead of enum

try use static final for constant


HashMap is heavy if you can replace it by  SparseArray it would be much more efficency

Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.

Every class in Java (including anonymous inner classes) uses about 500 bytes of code 

Every class instance has 12-16 bytes of RAM overhead


Be careful with code abstractions

Often, developers use abstractions simply as a "good programming practice," because abstractions can improve code flexibility and maintenance. However, abstractions come at a significant cost: generally they require a fair amount more code that needs to be executed, requiring more time and more RAM for that code to be mapped into memory. So if your abstractions aren't supplying a significant benefit, you should avoid them.



1_Synchronized method 2_Synchronized statement


************************************************************

Synchronize of two threads on an object (class SynDemo)


public class SeekBarActivity extends Activity {

    /** Called when the activity is first created. */

    SeekBar seek;

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        SynDemo d=new  SynDemo();

        Thread1 th=new Thread1(d);

        Thread2 th2=new Thread2(d);

        

        th.start();

        th2.start();

    }

    

    private class Thread1 extends Thread{

        private SynDemo d;

        public Thread1(SynDemo sDemo) {

            d=sDemo;

        }

        @Override

        public void run() {

            super.run();

            d.printNumber("Thread1");

        }

      }

    

    private class Thread2 extends Thread{

        

        private SynDemo d;

        public Thread2(SynDemo sDemo) {

            d=sDemo;

        }

        @Override

        public void run() {

            super.run();

            d.printNumber("Thread2");

        }

    }

    private class SynDemo {

///quickly when system sees this word 'synchronized" it acquire a intrinsic Lock for it! when methode return, it is automatically release

        

        synchronized void printNumber(String string){

            for(int i=0;i<2000;i++){

                Log.i(""+string,String.valueOf(i));

            }

        }

    }

    

}


*****************************************************************

wait on an object will release lock on object so allowing other threads to access it which were previously in waiting line



Unlike synchronized methods, synchronized statements must specify the object that provides the intrinsic lock:


Deadlock: block situation in which two or more threads are waiting to access an object bu lock not released or...!



class parent

{


static class A

{

public A(){}

public synchronized void methodA()

{

doSomeProcess();



}

public synchronized void doSomeProcess()

{


}

}


......

A a=new A()

A b=new A()

Thread thA=new Thread()

{

    @Override

    public void run() {

        b. methodA();

    }

};


thread.start();




Thread thB=new Thread()

{

    @Override

    public void run() {

        a. methodA();

    }

};


thread.start();


}

 

Avoid leak memory in your pattern:

One of the most usuall pattern in your application is to use one or more non-static inner or anonymous class in your activity , which if mix with message handling create very serious leaking issues! especially when we store them in a static variable!

the root cause of this issue is the fact that In Java, non-static inner and anonymous classes hold an implicit reference to their outer class but Static inner classes, on the other hand, do not.let's see an example in onCreate of an Activity add this bloc :


 Runnable runnable = new Runnable() {

                @Override

                public void run() {

                    // infinit loop processing

                    for (; ; ) {

                        liveCount++;

                        Log.d("runnable", String.valueOf(liveCount));

                    }

                }


            };



        new Handler().post(runnable);

        finish();


This activity keep living in memory even after finish is done!because anonymous runnable class keep a strong refrence to myActivity (remind references by default are strong)

To avoid this situation use static class rather than non-static , in order to not be in the meme section of heap, then to keep a pointer to running activity use WeakReference which is a generic class and pass the activity to its constructor.this way GC can remove it from memory because it’s not protected anymore by GC and remove it.

View Performance


Using Loaders in Android

1)To use AsyncTaskLoader you should first call initLoader()

2)when using Loaders ,it happens in some devices loadInBackground is not call in your AsyncTaskLoader subclass whithin

your code, in this case replace initLoader() by initLoader().forceLoad(); 

===================================

View & graphic performance

using Hardware Acceleration: from Version 14 to higher there is no need to enable it from manifest

it's enabled by default:

Hardware Acceleration in general can be applied at the Activity level or a specific view or canvas

when to apply: for Scalling , Rotation, translate,transfer,.... HA is good but for drawing not so good so control it by api like view.setLayerType(View.LAYER_TYPE_HARDWARE, null);or ..for example


 public PieView(Context context) {

           super(context);

           if (!isInEditMode()) {

               setLayerType(View.LAYER_TYPE_HARDWARE, null);

           }

       }


Notice: HHA is automatically enabled in API14 and higher 

 © Xosrov 2016