original source: https://android.jlelse.eu/memory-leak-patterns-in-android-4741a7fcb570

  1. Leak activity to a static reference
  2. Leak activity to a worker thread
  3. Leak thread itself

크게는 세가지 부류로 구분된다.

첫번째 부류에서 세분화된 예들

  1. Leak Activity to a static view (https://github.com/frank-tan/SinsOfMemoryLeaks/blob/LEAK/app/src/main/java/com/franktan/memoryleakexamples/viastaticreference/LeakActivityToStaticViewActivity.java)
  2. Leak Activity to a static variable (https://github.com/frank-tan/SinsOfMemoryLeaks/blob/LEAK/app/src/main/java/com/franktan/memoryleakexamples/viastaticreference/LeakActivityToStaticVariableActivity.java)
  3. Leak Activity to a singleton object (https://github.com/frank-tan/SinsOfMemoryLeaks/blob/LEAK/app/src/main/java/com/franktan/memoryleakexamples/viastaticreference/LeakActivityToSingletonActivity.java)
  4. Leak Activity to a static instance of a inner class of the activity (https://github.com/frank-tan/SinsOfMemoryLeaks/blob/LEAK/app/src/main/java/com/franktan/memoryleakexamples/viastaticreference/LeakActivityToStaticInnerClassActivity.java)

스태틱으로 지정하는 경우  그안의 내용이 app이 끝날때 까지 유지되므로 주의해야 한다. 

1 번 예제 코드 (static으로 view를 참조하는 변수를 만든 경우)

public class LeakActivityToStaticViewActivity extends AppCompatActivity {

    // FIXME: 2/26/17 static view will leak the activity. To fix it, make it non-static
    static TextView label;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        label = new TextView(this);
        label.setText(getString(R.string.leak_explanation_static_view, getString(R.string.instruction_check_for_leaks)));

        setContentView(label);
    }
}

2번 예제 코드  (static으로 activity를 참조하는 변수를 만든 경우)

public class LeakActivityToStaticVariableActivity extends AppCompatActivity {
    // FIXME: 2/26/17 static reference to the activity will leak the activity.
    // To fix it, set it null onDestroy or use weak reference
    static Activity activity = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_leak_context_to_static_variable);
        TextView textView = (TextView) findViewById(R.id.textView);

        if (activity == null) {
            activity = this;
        }
    }
}

3번 예제 코드  (singleton obj를 참조하는 변수를 만든 경우)

public class LeakActivityToSingletonActivity extends AppCompatActivity {

    SomeSingletonManager someSingletonManager = null;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_leak_context_to_singleton);
        // FIXME: fix option 1: instead of passing `this` to getInstance(), pass getApplicationContext()
        someSingletonManager = SomeSingletonManager.getInstance(this);
    }

4번 예제 코드  (static으로 inner class obj를 참조하는 변수를 만든 경우)

public class LeakActivityToStaticInnerClassActivity extends AppCompatActivity {

    private static SomeInnerClass someInnerClass;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_leak_static_reference_to_inner_class);

        if (someInnerClass == null) {
            someInnerClass = new SomeInnerClass();
        }
    }

두번째부류에서 세분화된 예들

  1. Leak Activity to a thread (https://github.com/frank-tan/SinsOfMemoryLeaks/blob/LEAK/app/src/main/java/com/franktan/memoryleakexamples/vialongrunningtask/LeakActivityToThreadActivity.java)
  2. Leak Activity to a handler (https://github.com/frank-tan/SinsOfMemoryLeaks/blob/LEAK/app/src/main/java/com/franktan/memoryleakexamples/vialongrunningtask/LeakActivityToHandlerActivity.java)
  3. Leak Activity to an AsyncTask (https://github.com/frank-tan/SinsOfMemoryLeaks/blob/LEAK/app/src/main/java/com/franktan/memoryleakexamples/vialongrunningtask/LeakActivityToAsyncTaskActivity.java)

두번째 세번째 분류의 내용을 종합해 보면 activity내에서 발생된 thread의 작업이 activity lifecycle보다 길수있다. activity가 종료된 후에도 작업중인 thread에 의해 memory leak이 발생할수 있다. 그러므로 activity onDestroy()에서 thread를 적당히 처리해야 한다.

  • 일정 작업의 delay하는 방법

https://stackoverflow.com/a/24104427/3151712

If you want to pause then use java.util.concurrent.TimeUnit:

TimeUnit.SECONDS.sleep(1);

To sleep for one second or

TimeUnit.MINUTES.sleep(1);

To sleep for a minute.

https://stackoverflow.com/a/14168900/3151712

try
{
Thread.sleep(5 * 1000);
}catch(InterruptedException ie)
{
 //Log message if required.
}

https://stackoverflow.com/a/38524606/3151712

new CountDownTimer(6000, 1000) {
            public void onFinish() {
               mProgressDialog.dismiss();
              // my whole code
            }

            public void onTick(long millisUntilFinished) {
                mProgressDialog.show();
            }
        }.start();