Android內存優化

一、內存泄漏

1、什麼是內存泄漏

內存泄漏指在程序運行過程中分配的內存空間沒有及時釋放,導致內存空間佔用過多,造成程序的崩潰或者系統的崩潰的現象。一般體現為App啟動後,內存不斷增加,操作時間越長,內存越大,容易造成ANR或者崩潰。

2、常見的內存泄漏場景

a.靜態變量被持有:

“`
public class Singleton{
private static Singleton instance;
public static Singleton getInstance(){
if(instance ==null){
instance =new Singleton();
}
return instance;
}
//…
}
“`

在單例模式中,只要有一個對象持有了該類的引用,那麼這個對象和其中的所有成員信息都不會被回收,從而引發了內存泄漏。

b.handler引起內存泄漏:

“`
public class MainActivity extends Activity{
private Handler mHandler =new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
//…
}
“`

在Activity中使用了handler,由於handler持有外部類Activity的引用,那麼當Activity被摧毀時,由於handler還持有Acitivity的引用,會導致Activity無法被回收。此時,建議在Activity退出時清除handler的消息隊列。

c.監聽器泄漏:

“`
public class MainActivity extends Activity{
private MyOnClickListener mListener =new MyOnClickListener(){

@Override
public void onClick(View view) {

}
};
//…

@Override
protected void onDestroy() {
super.onDestroy();
mButton.setOnClickListener(null);
}
}
“`

在Activity中使用監聽器時,如果不及時銷毀,會造成Activity的內存泄漏,同樣的,在Activity銷毀時,需要及時清除持有監聽器的引用。

二、Bitmap優化

1、Bitmap內存計算

Bitmap在內存中佔用的大小=圖片的寬度*圖片的高度*每個像素點的位元組數。

2、Bitmap內存優化

a.採樣率縮放

“`
public static Bitmap decodeSampledBitmapFromFile(String filename,int width,int height){
final BitmapFactory.Options options =new BitmapFactory.Options();
options.inJustDecodeBounds =true;
BitmapFactory.decodeFile(filename,options);
options.inSampleSize =calculateInSampleSize(options,width,height);
options.inJustDecodeBounds =false;
return BitmapFactory.decodeFile(filename,options);
}

public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth,int reqHeight){
final int height =options.outHeight;
final int width =options.outWidth;
int inSampleSize =1;

if(height> reqHeight|| width >reqWidth ){
final int heightRatio =Math.round((float)height/ (float)reqHeight);
final int widthRatio =Math.round((float)width/ (float)reqWidth);
inSampleSize =heightRatio<widthRatio? heightRatio:widthRatio;
}
return inSampleSize;
}
“`

b.使用軟引用和弱引用

“`
public HashMap<String, SoftReference> imageCache =new HashMap<String, SoftReference>();

//…

SoftReference reference = new SoftReference(bitmap);

imageCache.put(url, reference);
“`

c.LruCache

“`
public class MemoryCache extends LruCache {

public MemoryCache(int maxSize) {
super(maxSize);
}

@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes()*value.getHeight();
}

@Override
protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {
super.entryRemoved(evicted, key, oldValue, newValue);
//釋放oldValue的內存空間
oldValue.recycle();
}
}

//…

int maxMemory = (int)(Runtime.getRuntime().maxMemory()/1024);
int cacheSize =maxMemory/8;

mMemoryCache =new MemoryCache(cacheSize);
“`

三、布局優化

1、Layout XML的優化

a.使用include標籤

“`

“`

b.使用RelativeLayout,減少deep-level嵌套

“`

“`

c.不使用過於複雜的布局文件

2、代碼布局優化

a.手動布局時,減少measure和layout的操作次數

“`
private LinearLayout layoutExample;
layoutExample.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));
layoutExample.setOrientation(LinearLayout.VERTICAL);

TextView textView=new TextView(context);
textView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
textView.setText(“Custom Text”);

layoutExample.addView(textView);

setContentView(layoutExample);
“`

b.使用自定義View,復用已有的控件

四、資源文件優化

1、資源文件分類

將資源文件按不同的類型進行分類,方便開發和維護。

2、資源文件壓縮

a.使用lint工具

打開Android Studio中的預編譯檢查功能,可檢測和提示不必要的資源文件,方便開發時的及時優化。

b.使用TinyPNG或者PngQuant工具

可以無損或者有損地對圖片資源進行壓縮,減小apk的大小。

五、線程優化

1、線程池的使用

a.避免反覆地創建和銷毀線程,提高線程的重複利用率。

b.通過Executors類創建線程池,來控制線程的數量和資源。

“`
//使用newFixedThreadPool來創建線程池

ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);

//提交任務

threadPool.execute(new Runnable() {
@Override
public void run() {
//…
}
});
“`

2、AsyncTask的使用

通過AsyncTask來處理UI線程和後台線程的交互,避免在主線程中進行長時間的操作,從而導致ANR。

“`
public class DownloadTask extends AsyncTask{
@Override
protected String doInBackground(String… params) {
//這裡進行耗時操作
return result;
}

@Override
protected void onProgressUpdate(Integer… values) {
super.onProgressUpdate(values);
//更新進度條
}

@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
//更新UI
}
}
“`

3、使用Handler和ThreadLocal減少內存佔用

a.Handler

“`
private static class MyHandler extends Handler{

private final WeakReference mActivity;

public MyHandler(Activity activity){
mActivity =new WeakReference(activity);
}

@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(mActivity.get()!=null){
//執行UI操作或者其他操作
}
}
}

private MyHandler mHandler =new MyHandler(this);
“`

b.ThreadLocal

“`
private ThreadLocal threadLocal =new ThreadLocal(){
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
}
};

private class SimpleThread extends Thread{
@Override
public void run() {
SimpleDateFormat sdf =threadLocal.get();
//…
}
}
“`

六、APP啟動優化

1、延遲加載

a.使用Fragment或者ViewPager可以延遲加載不必要的資源或者頁面。

“`
public class MyFragment extends Fragment{
//…
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser){
//加載數據或者頁面
}else{
//釋放資源
}
}
}
“`

b.通過線程池進行延遲加載和預加載,提高App啟動速度。

2、懶加載

延遲加載過後,還可以通過懶加載的方式加載不必要的資源,提高App的啟動速度。

“`
public class LazyLoadFragment extends Fragment{

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView =inflater.inflate(R.layout.fragment_lazy,container,false);
return rootView;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if(getUserVisibleHint()){
//加載數據或者頁面
}
}

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);

if(isVisibleToUser&&isAdded()){
//加載數據或者頁面
}
}
}
“`

七、總結

內存優化是Android開發中的一個重要環節,在開發過程中,多注意內存泄漏的問題,對Bitmap進行優化和管理,對布局和資源文件進行分類和壓縮,選用合適的線程池和AsyncTask,延遲和懶加載,可以大大提高App的啟動速度和運行效率。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/249551.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-12 17:13
下一篇 2024-12-12 17:13

相關推薦

  • Android ViewPager和ScrollView滑動衝突問題

    Android開發中,ViewPager和ScrollView是兩個常用的控件。但是當它們同時使用時,可能會發生滑動衝突的問題。本文將從多個方面介紹解決Android ViewPa…

    編程 2025-04-28
  • Android如何點擊其他區域收起軟鍵盤

    在Android應用中,當輸入框獲取焦點彈出軟鍵盤後,我們希望能夠點擊其他區域使軟鍵盤消失,以提升用戶體驗。本篇文章將說明如何實現這一功能。 一、獲取焦點並顯示軟鍵盤 在Andro…

    編程 2025-04-28
  • Android Studio HUD 實現指南

    本文將會以實例來詳細闡述如何在 Android Studio 中使用 HUD 功能實現菊花等待指示器的效果。 一、引入依賴庫 首先,我們需要在 build.gradle 文件中引入…

    編程 2025-04-27
  • Android和Vue3混合開發方案

    本文將介紹如何將Android和Vue3結合起來進行混合開發,以及其中的優勢和注意事項。 一、環境搭建 在進行混合開發之前,需要搭建好相應的開發環境。首先需要安裝 Android …

    編程 2025-04-27
  • Android Java Utils 可以如何提高你的開發效率

    Android Java Utils 是一款提供了一系列方便實用的工具類的 Java 庫,可以幫助開發者更加高效地進行 Android 開發,提高開發效率。本文將從以下幾個方面對 …

    編程 2025-04-27
  • Android JUnit測試完成程序自動退出決方法

    對於一些Android JUnit測試的開發人員來說,程序自動退出是一個經常面臨的困擾。下面從多個方面給出解決方法。 一、檢查測試代碼 首先,我們應該仔細檢查我們的測試代碼,確保它…

    編程 2025-04-25
  • Android Activity啟動流程

    一、Activity概述 Android應用程序是由許多Activity組成的。一個Activity代表一個屏幕上的窗口。用戶與應用程序交互時,Activity會接收用戶的輸入並處…

    編程 2025-04-25
  • Android單元測試詳解

    一、單元測試概述 單元測試是指對軟件中的最小可測試單元進行檢查和驗證。在Android開發中,單元測試是非常重要的一環,可以保證代碼的質量、穩定性以及可維護性。 在Android開…

    編程 2025-04-25
  • Android WebView加載本地HTML

    一、介紹 Android WebView是一個內置的瀏覽器,它允許開發人員在應用中嵌入網頁。使用WebView可以輕鬆地在應用程序中顯示本地或遠程的HTML內容。本篇文章將重點講述…

    編程 2025-04-24
  • Android Wakelock詳解

    一、什麼是Android Wakelock? 在Android應用開發中,Wakelock被廣泛應用於保持屏幕或CPU處於喚醒狀態,以便應用程序可以繼續執行後台任務,直到任務完成。…

    編程 2025-04-24

發表回復

登錄後才能評論