Android Memory Leak

线程也是造成内存泄露的一个重要的源头。线程产生内存泄露的主要原因在于线程生命周期的不可控。
1.看一下下面是否存在问题

public class ThreadActivity extends Activity {  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        new MyThread().start();  
    }  

    private class MyThread extends Thread {  
        @Override  
        public void run() {  
            super.run();  
            dosomthing();  
        }  
    }  
    private void dosomthing(){  

    }  
}  

 

这段代码很平常也很简单,是我们经常使用的形式。

真的没有问题吗?
我们思考一个问题:假设MyThread的run函数是一个很费时的操作,当我们开启该线程后,将设备的横屏变为了竖屏,
一般情况下当屏幕转换时会重新创建Activity,按照我们的想法,老的Activity应该会被销毁才对,然而事实上并非如此。
由于我们的线程是Activity的内部类,所以MyThread中保存了Activity的一个引用,当MyThread的run函数没有结束时,
MyThread是不会被销毁的,因此它所引用的老的Activity也不会被销毁,因此就出现了内存泄露的问题。

2.这种线程导致的内存泄露问题应该如何解决呢?
• 第一、将线程的内部类,改为静态内部类。
• 第二、在线程内部采用弱引用保存Context引用。 代码如下:

public class ThreadAvoidActivity extends Activity {  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        new MyThread(this).start();  
    }  

    private void dosomthing() {  

    }  

    private static class MyThread extends Thread {  
        WeakReference mThreadActivityRef;  

        public MyThread(ThreadAvoidActivity activity) {  
            mThreadActivityRef = new WeakReference(  
                    activity);  
        }  

        @Override  
        public void run() {  
            super.run();  
            if (mThreadActivityRef == null)  
                return;  
            if (mThreadActivityRef.get() != null)  
                mThreadActivityRef.get().dosomthing();  
            // dosomthing  
        }  
    }  
}  

 

上面的两个步骤其实是切换两个对象的双向强引用链接
1. 静态内部类:切断Activity 对于 MyThread的强引用。
2. 弱引用: 切断MyThread对于Activity 的强引用。

3.AsynTask 内部类会如何呢?
我们思考一个问题:假设MyThread的run函数是一个很费时的操作,当我们开启该线程后,将设备的横屏变为了竖屏,
一般情况下当屏幕转换时会重新创建Activity,按照我们的想法,老的Activity应该会被销毁才对,然而事实上并非如此。
由于我们的线程是Activity的内部类,所以MyThread中保存了Activity的一个引用,当MyThread的run函数没有结束时,
MyThread是不会被销毁的,因此它所引用的老的Activity也不会被销毁,因此就出现了内存泄露的问题。代码如下:

public abstract class WeakAsyncTask<Params, Progress, Result, WeakTarget>  
    extends AsyncTask<Params, Progress, Result> {  
    protected WeakReference mTarget;  

    public WeakAsyncTask(WeakTarget target) {  
        mTarget = new WeakReference(target);  
    }  

    @Override  
    protected final void onPreExecute() {  
        final WeakTarget target = mTarget.get();  
        if (target != null) {  
            this.onPreExecute(target);  
        }  
    }  

    @Override  
    protected final Result doInBackground(Params... params) {  
        final WeakTarget target = mTarget.get();  
        if (target != null) {  
            return this.doInBackground(target, params);  
        } else {  
            return null;  
        }  
    }  

    @Override  
    protected final void onPostExecute(Result result) {  
        final WeakTarget target = mTarget.get();  
        if (target != null) {  
            this.onPostExecute(target, result);  
        }  
    }  

    protected void onPreExecute(WeakTarget target) {  
        // Nodefaultaction  
    }  

    protected abstract Result doInBackground(WeakTarget target,  
            Params... params);  

    protected void onPostExecute(WeakTarget target, Result result) {  
        // Nodefaultaction  
    }  
} 

 

 

posted @ 2015-01-21 15:04  justin.wang  阅读(243)  评论(0)    收藏  举报