安卓內存優(yōu)化案例三

安卓內存優(yōu)化是一個很重要的話題聋涨,有很多方面可以考慮,比如避免內存泄漏溉躲、減少內存抖動榜田、優(yōu)化圖片加載、使用緩存和對象池等锻梳。下面我舉一些代碼案例箭券,分別展示不合適的寫法和高性能的寫法。
歡迎評論區(qū)留言指正和補充唱蒸。

使用靜態(tài)內部類或者弱引用來避免非靜態(tài)內部類持有外部類的引用邦鲫,造成內存泄漏。

// 不合適的寫法
public class MainActivity extends AppCompatActivity {

    private MyTask task;

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

        task = new MyTask();
        task.execute();
    }

    private class MyTask extends AsyncTask<Void, Void, Void> {
        // 這是一個非靜態(tài)內部類,它會隱式地持有外部類的引用
        @Override
        protected Void doInBackground(Void... params) {
            // do some background work
            return null;
        }
    }
}

// 高性能的寫法
public class MainActivity extends AppCompatActivity {

    private MyTask task;

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

        task = new MyTask(this);
        task.execute();
    }

    private static class MyTask extends AsyncTask<Void, Void, Void> {
        // 這是一個靜態(tài)內部類庆捺,它不會持有外部類的引用
        private WeakReference<MainActivity> activityRef;

        public MyTask(MainActivity activity) {
            activityRef = new WeakReference<>(activity);
        }

        @Override
        protected Void doInBackground(Void... params) {
            // do some background work
            return null;
        }
    }
}

這樣做可以避免內存泄漏古今,因為如果MainActivity被銷毀,而MyTask還在后臺運行滔以,那么非靜態(tài)內部類會導致MainActivity無法被回收捉腥,而靜態(tài)內部類或者弱引用則不會。這樣可以節(jié)省內存空間你画,并提高性能抵碟。

使用單例模式時,注意使用Application的Context坏匪,而不是Activity的Context拟逮,避免Activity無法被回收。

// 不合適的寫法
public class MySingleton {

    private static MySingleton instance;
    private Context context;

    private MySingleton(Context context) {
        this.context = context;
    }

    public static MySingleton getInstance(Context context) {
        if (instance == null) {
            instance = new MySingleton(context); // 這里使用了Activity的Context适滓,會導致Activity無法被回收
        }
        return instance;
    }
}

// 高性能的寫法
public class MySingleton {

    private static MySingleton instance;
    private Context context;

    private MySingleton(Context context) {
        this.context = context.getApplicationContext(); // 這里使用了Application的Context敦迄,不會導致Activity無法被回收
    }

    public static MySingleton getInstance(Context context) {
        if (instance == null) {
            instance = new MySingleton(context);
        }
        return instance;
    }
}

這樣做可以避免內存泄漏,因為如果Activity被銷毀凭迹,而MySingleton還在使用它的Context罚屋,那么Activity無法被回收,而Application的Context則不會嗅绸。這樣可以節(jié)省內存空間脾猛,并提高性能。

使用Proguard或者R8等工具來混淆和壓縮代碼鱼鸠,減少方法數(shù)和字節(jié)碼大小猛拴。例如:

android {
  buildTypes {
    release {
      minifyEnabled true // 這里開啟了代碼混淆和壓縮
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
      shrinkResources true // 這里開啟了資源文件壓縮
    }
  }
}

這樣做可以減少APK的體積,提高應用的安全性和運行效率瞧柔。

使用Lint工具來檢測和移除無用的資源文件漆弄,減少APK的體積。例如:

android {
  lintOptions {
    checkReleaseBuilds true // 這里開啟了Lint檢查
    abortOnError true // 這里設置了如果發(fā)現(xiàn)錯誤就終止編譯
  }
}

這樣做可以減少APK的體積造锅,提高應用的運行效率和質量。

使用inBitmap選項來復用Bitmap的內存空間廉邑,減少內存分配哥蔚。例如:

// 不合適的寫法
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image, options); // 這里沒有使用inBitmap選項,會導致每次都分配新的內存空間

// 高性能的寫法
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inBitmap = reusableBitmap; // 這里使用了inBitmap選項蛛蒙,會復用已有的內存空間糙箍,reusableBitmap是一個合適大小的位圖對象
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image, options);

這樣做可以減少內存分配和回收的次數(shù),提高性能和流暢度牵祟。

使用inSampleSize選項來按比例縮放圖片深夯,避免加載過大的圖片。例如:

// 不合適的寫法
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image, options); // 這里沒有使用inSampleSize選項,會加載原始大小的圖片咕晋,占用內存空間雹拄,并可能導致OOM

// 高性能的寫法
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.drawable.image, options); // 這里先獲取圖片的原始寬高,不加載圖片到內存中
int width = options.outWidth;
int height = options.outHeight;
int inSampleSize = 1; // 這里根據(jù)需要計算一個合適的縮放比例掌呜,例如根據(jù)視圖的大小和屏幕密度等因素
options.inJustDecodeBounds = false;
options.inSampleSize = inSampleSize; // 這里使用inSampleSize選項滓玖,會按比例縮放圖片,節(jié)省內存空間质蕉,并避免OOM
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image, options);

這樣做可以避免加載過大的圖片势篡,節(jié)省內存空間,并提高圖片加載的效率和質量模暗。

優(yōu)化布局文件禁悠,減少布局層級和冗余控件,使用include兑宇、merge绷蹲、ViewStub等標簽來復用和延遲加載布局。例如:

<!-- 不合適的寫法 -->
<LinearLayout android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Title" />

    <LinearLayout android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <ImageView android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/icon" />

        <TextView android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Content" />

    </LinearLayout>

</LinearLayout>

<!-- 高性能的寫法 -->
<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <TextView android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Title" />

    <ImageView android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/icon" />

    <TextView android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Content" />

</merge>

這樣做可以減少布局層級和冗余控件顾孽,提高布局加載和渲染的效率和流暢度祝钢。如果想要復用和延遲加載布局,可以使用include若厚、merge拦英、ViewStub等標簽來實現(xiàn)。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末测秸,一起剝皮案震驚了整個濱河市疤估,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌霎冯,老刑警劉巖铃拇,帶你破解...
    沈念sama閱讀 223,002評論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異沈撞,居然都是意外死亡慷荔,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評論 3 400
  • 文/潘曉璐 我一進店門缠俺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來显晶,“玉大人,你說我怎么就攤上這事壹士×坠停” “怎么了?”我有些...
    開封第一講書人閱讀 169,787評論 0 365
  • 文/不壞的土叔 我叫張陵躏救,是天一觀的道長唯笙。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么崩掘? 我笑而不...
    開封第一講書人閱讀 60,237評論 1 300
  • 正文 為了忘掉前任七嫌,我火速辦了婚禮,結果婚禮上呢堰,老公的妹妹穿的比我還像新娘抄瑟。我一直安慰自己,他們只是感情好枉疼,可當我...
    茶點故事閱讀 69,237評論 6 398
  • 文/花漫 我一把揭開白布皮假。 她就那樣靜靜地躺著,像睡著了一般骂维。 火紅的嫁衣襯著肌膚如雪惹资。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,821評論 1 314
  • 那天航闺,我揣著相機與錄音褪测,去河邊找鬼。 笑死潦刃,一個胖子當著我的面吹牛侮措,可吹牛的內容都是我干的。 我是一名探鬼主播乖杠,決...
    沈念sama閱讀 41,236評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼分扎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了胧洒?” 一聲冷哼從身側響起畏吓,我...
    開封第一講書人閱讀 40,196評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎卫漫,沒想到半個月后菲饼,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,716評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡列赎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,794評論 3 343
  • 正文 我和宋清朗相戀三年宏悦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片粥谬。...
    茶點故事閱讀 40,928評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡肛根,死狀恐怖,靈堂內的尸體忽然破棺而出漏策,到底是詐尸還是另有隱情,我是刑警寧澤臼氨,帶...
    沈念sama閱讀 36,583評論 5 351
  • 正文 年R本政府宣布掺喻,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏感耙。R本人自食惡果不足惜褂乍,卻給世界環(huán)境...
    茶點故事閱讀 42,264評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望即硼。 院中可真熱鬧逃片,春花似錦、人聲如沸只酥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,755評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽裂允。三九已至损离,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間绝编,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,869評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留捕捂,地道東北人漂洋。 一個月前我還...
    沈念sama閱讀 49,378評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像逗堵,于是被迫代替她去往敵國和親秉氧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,937評論 2 361

推薦閱讀更多精彩內容