2014-09-12 42 views
1

我發現幾個主題描述了類似的問題,但沒有發現非常簡單的Android應用程序所創建的內存泄漏的解決方案:背景圖像內存泄露

AndroidManifest.xml中

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
      package="cz.reloecc.testBackground" 
      android:versionCode="1" 
      android:versionName="1.0"> 
    <uses-sdk android:minSdkVersion="10"/> 
    <application android:label="@string/app_name" 
       android:icon="@drawable/ic_launcher"> 
     <activity android:name="TestBackgroundActivity" 
        android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" 
        android:label="@string/app_name"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN"/> 
       <category android:name="android.intent.category.LAUNCHER"/> 
      </intent-filter> 
     </activity> 
    </application> 
</manifest> 


main.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
      android:orientation="vertical" 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      android:background="@drawable/ui"> 
</LinearLayout> 


TestBackgroundActivity.java

public class TestBackgroundActivity extends Activity { 
    @Override 
    public void onCreate(Bundle savedInstanceState){ 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
    } 
} 


雖然改變我設備的定向(的NVIDIA Tegra注7)logcat的是注意到:

cz.reloecc.testBackground I/dalvikvm-heap﹕ Grow heap (frag case) to 35.625MB for 12904976-byte allocation 

與大致每個週轉時間(對於最大版本的圖像)都有13MB附加費

到我的最大堆(64MB):

cz.reloecc.testBackground E/dalvikvm-heap﹕ Out of memory on a 12904976-byte allocation. 
cz.reloecc.testBackground I/dalvikvm﹕ at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) 
.. 
cz.reloecc.testBackground I/dalvikvm﹕ at cz.reloecc.testBackground.TestBackgroundActivity.onCreate(TestBackgroundActivity.java:13) 


BUT! DPI OR drawable- [X | M | L] dpi的夾 問題當我從抽拉-陸地[| | M L X]刪除ui.png(其被設置爲背景)不堅持在res文件夾中。 因此,如果我只有一個版本的背景圖像,我可以打開設備一個長周..

這裏是我的問題:如何處理多個版本的drawable(設置爲背景)避免內存泄漏?


//編輯:我管理的處置,回收,銷燬,調零資源或其持有人試了幾次,最後一個是基於Aeshang的建議:


=== 2.0版 = ==

Resources.java

public class Resources { 

    public Resources(Context context){ 
     this.context = context; 
    } 

    public Drawable getImage(int id){ 
     if(images.indexOfKey(id) < 0){ 
      Drawable drawable = context.getResources().getDrawable(id); 
      images.put(id, drawable); 
     } 

     return images.get(id); 
    } 

    public void disposeImages(){ 
     int key; 

     for(int i = 0; i < images.size(); i++) { 
      key = images.keyAt(i); 
      Drawable drawable = images.get(key); 

      if(drawable instanceof BitmapDrawable){ 
       if(drawable instanceof BitmapDrawable){ 
        Log.i(TestBackgroundActivity.LOG_TAG, "Recycling image " + key); 
        ((BitmapDrawable)drawable).getBitmap().recycle(); 
       } 
      } 
     } 
    } 

    public void disposeAll(){ 
     disposeImages(); 
     images.clear(); 
    } 

    private SparseArray<Drawable> images = new SparseArray<Drawable>(); 
    private Context context; 
} 


TestBackgroundActivity。java的

public class TestBackgroundActivity extends Activity { 

    public static String LOG_TAG = "[TestBG]"; 

    @Override 
    public void onCreate(Bundle savedInstanceState){ 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     resources = new Resources(getApplicationContext()); 
     LinearLayout mainLayout = (LinearLayout)findViewById(R.id.mainLayout); 
     mainLayout.setBackgroundDrawable(resources.getImage(R.drawable.ui)); 
    } 

    @Override 
    protected void onDestroy(){ 
     resources.disposeAll(); 

     super.onDestroy(); 
    } 

    private Resources resources; 
} 
+0

創建一個主題類,它提供您需要的所有圖像,並在析構函數/處理方法中處理所有(尚未處理的)圖像。 – StackFlowed 2014-09-12 21:09:31

+0

@Aeshang: thx爲您的答案,因爲這我嘗試了幾種不同的方式,也許我不知道如何正確處置BitmapDrawable。我編輯了我的文章,以便您可以在2.0版中看到當前的解決方案..仍然相同.. – Reloecc 2014-09-12 22:03:17

+0

使用ImageDescriptor創建圖像並處理圖像並使描述符爲空..檢查部分代碼示例... – StackFlowed 2014-09-13 07:56:06

回答

0

好吧,

這應該肯定的工作。在另外兩個設備上測試過,而且應用程序正在抱怨內存堆的高速增長。它後面就是gc'ing。

我的特格拉筆記7是痛苦。我將不得不找出這個地獄的正確來源。

//編輯: 細,要求MainActivity

中的onDestroy

System.gc(); 

()和應用程序是永恆的..誰知道這是爲什麼?

0

使用第三方庫加載可繪製

PicassoUniversal Image Loader

他們會自動處理大量位圖

而且即將繪項目

用戶1920X1080分辨率的圖像,並把它們拖下wable-xxhdpi文件夾中的每一件事情正常工作

+0

感謝您的建議,但我不相信我們需要一個複雜的圖像加載器只提供一個BG圖像。 沒有必要有這麼大的圖像產生泄漏,我最小的一個是640x400,它只需要更多的旋轉。 此外,我將通過這個裝載器獲取Bitmaps或ImageView,我不能在API <16中將其設置爲背景圖像。 有幾個不同的方法來設置我的背景,但我想在選擇其他方式之前解決這個問題。 – Reloecc 2014-09-13 18:06:15