編輯:關於Android編程
線程也是造成內存洩露的一個重要的源頭。線程產生內存洩露的主要原因在於線程生命周期的不可控。
/** * * @version 1.0.0 * @author Abay Zhuang
* Create at 2014-7-17 */ 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也不會被銷毀,因此就出現了內存洩露的問題。
第二、在線程內部采用弱引用保存Context引用。 代碼如下:
/** * * @version 1.0.0 * @author Abay Zhuang
* Create at 2014-7-17 */ 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 { WeakReferencemThreadActivityRef; 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 } } }
有些人喜歡用Android提供的AsyncTask,但事實上AsyncTask的問題更加嚴重,
Thread只有在run函數不結束時才出現這種內存洩露問題,然而AsyncTask內部的實現機制是運用了ThreadPoolExcutor,
該類產生的Thread對象的生命周期是不確定的,是應用程序無法控制的,
因此如果AsyncTask作為Activity的內部類,就更容易出現內存洩露的問題。
代碼如下:
/** * * 弱引用 * @version 1.0.0 * @author Abay Zhuang
* Create at 2014-7-17 */ public abstract class WeakAsyncTaskextends AsyncTask { 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 } }
先放上一張效果圖:在這裡,我對自己的筆記本全屏截圖,然後當作自定義ImageView的src內容放在真機上運行。可以看到這裡的圖片是可以移動和縮放的。在這裡先說清一點,如
你以為頭像更換很容易?或許對於用戶來講,在微信上更換一個頭像只是點擊頭像,選擇拍照或相冊,裁剪返回而已。但是對於程序員來說,要實現其實也挺吃力的(小火柴花了一個下午整理~
基於Android 6.0的源碼剖析, 分析Android啟動過程進程號為1的init進程的工作內容/system/core/init/Init.h/sys
先說下這個demo,這是一個模仿課程表的布局文件,雖然我是個菜鳥,但我還是想留給學習的人一些例子,先看下效果 然後再來看一下我們學校的app布局分析先上一張劃分