2013-02-07 48 views
2

更新(2.8.2013):感谢您在Gemap中学习Bitmap课程!我没有想到PNG是一种压缩格式(DOH时刻之一):DAndroid(仅限Jelly Bean) - MapActivity Overlay会导致内存不足错误

最后,尽管老版本的Android和Jelly Bean之间仍然存在问题......下面是一个屏幕截图堆在我的ICS手机和一个在果冻豆模拟器... ICS = < 6MB,JB => 22MB为完全相同的应用程序,完全相同的图像!

(使用< 6MB堆ICS):
https://docs.google.com/file/d/0B7GW5mJ5fr3XSTFYWU54VjdUTEk/edit?usp=sharing

(JB相同的应用程序 - 下面的一个 - 用> 22MB):
https://docs.google.com/file/d/0B7GW5mJ5fr3XUGlCdHNMUGJJVFE/edit?usp=sharing

因此,问题依然存在,什么是老版本在做什么来防止JB不符合的OOM条件?我怎样在Jelly Bean中覆盖这个,而不降低TON的分辨率(为了避免在JB中使用OOM,我必须去掉像素化的覆盖图)?


我在使用MapActivity和大型位图叠加层时遇到了Jelly Bean特定问题。在第一轮看Jelly Bean时,堆占用了22MB,而ICS占用了大约6MB。在增长后的每次运行中,根据你的位图的大小,它会给你一个OOM错误或者只是有一个超大的堆。

APP DESCRIPTION(此示例应用程序做什么)

下面是不是我原来的应用程序......我做了下面的代码复制的问题,并保持代码的简洁的全功能应用此;这是一个具有父活动(Start.java)和子活动(MainActivity.java)的应用程序。 Start.java只是一个带有加载MainActivity.java的按钮的屏幕(我不惜时间花费);

MainActivity.java将加载地图并有一个大的覆盖。我的覆盖图是来自GoogleMaps的纽约州的一部分剪辑,我在GIMP中添加了一个筛选器,因此您可以告诉它不同。然后通过“topLeft”GeoPoint和“bottomRight”GeoPoint将此叠加层“固定”到地图上,以便在缩放地图时缩放。

位图大小约为7MB ......所以看起来JellyBean的加载速度是3x(Heap是〜22MB)。看着堆,我看到它开始在8MB,然后迅速移动到16MB的012MB22MB。它也位于“res/drawable-nodpi”文件夹中。

我看到了以前的版本&这一问题的“修复”是把位图的“绘制-nodpi”这就是为什么住在这里,但豆形软糖这多工又回来了(老问题链接:https://stackoverflow.com/questions/13906037/android-mapactivity-overlay-bitmap-not-relasing-memory-when-finish-executes

的事情,我已经试过 1)试图把位图中所有 2)我一直试图使覆盖较小的绘制文件夹(-ldpi,-mdpi,-hdpi,-xhdpi)的...它确实远离OOM的崩溃,但仍然加载3倍...因为我的其他更复杂的应用程序有其他更小的图像,这不是一个解决方案 3)我试图创建一个“res/drawable”文件夹,并将位图放在这,它在MainActivity.jav的第一次加载时崩溃一个 - 似乎加载超过3倍) 4)在onDestroy()方法中增加了一个bitmap.recycle() - 这确实使这个示例应用程序不受OOM错误的影响,但如前所述,这是需要修复的3倍数据块最。

项目名称 - TestMapOverlayJB 全码ZIP档案(减去我的MAP关键 - 你需要添加你自己的) https://docs.google.com/file/d/0B7GW5mJ5fr3XY3h1MmFuREpoaDA/edit?usp=sharing

清单

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.example.testmapoverlayjb" 
    android:versionCode="1" 
    android:versionName="1.0" > 
    <uses-permission android:name="android.permission.INTERNET"/> 

    <uses-sdk 
     android:minSdkVersion="8" 
     android:targetSdkVersion="16" /> 

    <application 
     android:allowBackup="true" 
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" 
     android:theme="@style/AppTheme" > 
     <uses-library android:name="com.google.android.maps"/> 
     <activity 
      android:name=".Start" 
      android:label="@string/app_name" 
      android:theme="@android:style/Theme.NoTitleBar" > 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 
       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
     <activity android:name=".MainActivity" /> 
     <activity android:name=".MyBaseImageOverlay" /> 
    </application> 
</manifest> 

Start.java:

package com.example.testmapoverlayjb; 
import android.app.Activity; 
import android.content.ActivityNotFoundException; 
import android.content.Intent; 
import android.content.pm.ActivityInfo; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.Button; 
import android.widget.Toast; 

public class Start extends Activity { 

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

    Button buttonMainMenuSettings = (Button) findViewById(R.id.buttonNY); 
    buttonMainMenuSettings.setOnClickListener(new View.OnClickListener() { 
     public void onClick(View v) { 
     try { 
       Intent myIntent = new Intent(Start.this, MainActivity.class); 
       startActivity(myIntent); 
     } 
     catch (ActivityNotFoundException e) { 
      Toast.makeText(getBaseContext(), "Activity Not Found", Toast.LENGTH_SHORT).show(); 
     } 
    }}); 
    } 
} 

MainActivity.java:

package com.example.testmapoverlayjb; 
import com.google.android.maps.GeoPoint; 
import com.google.android.maps.MapActivity; 
import com.google.android.maps.MapController; 
import com.google.android.maps.MapView; 
import android.os.Bundle; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.view.Menu; 

public class MainActivity extends MapActivity { 
    Bitmap bitmapMapOverlay; 
    MyBaseImageOverlay baseLargeOverlay; 
    MapView mapView; 


    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     mapView = (MapView) findViewById(R.id.mapview); 
     mapView.setBuiltInZoomControls(true); 


     GeoPoint topLeft = new GeoPoint((int)40723714, (int)-74029412); 
     GeoPoint bottomRight = new GeoPoint((int)40704522, (int)-73976011); 
     bitmapMapOverlay = BitmapFactory.decodeResource(getResources(), R.drawable.ny_base1); 
     baseLargeOverlay = new MyBaseImageOverlay(topLeft, bottomRight, bitmapMapOverlay); 
     mapView.getOverlays().add(baseLargeOverlay); 
     MapController mapController = mapView.getController(); 
    mapController.setZoom(16); 
     mapController.setCenter(new GeoPoint((int)40715029,(int)-74001975)); 
    mapView.setSatellite(true); 
    mapView.setStreetView(false); 
     mapView.postInvalidate(); 
    } 

    @Override 
    protected boolean isRouteDisplayed() { 
     return false; 
    } 

    @Override 
    protected void onDestroy() { 
     bitmapMapOverlay.recycle(); 
     baseLargeOverlay = null; 
     mapView = null; 
     super.onDestroy(); 
    } 

} 

MyBaseImageOverlay.java:

package com.example.testmapoverlayjb; 
import android.graphics.Bitmap; 
import android.graphics.Canvas; 
import android.graphics.Point; 
import android.graphics.Rect; 
import com.google.android.maps.GeoPoint; 
import com.google.android.maps.MapView; 
import com.google.android.maps.Overlay; 

public class MyBaseImageOverlay extends Overlay { 
    private Bitmap baseBitmap; 
    GeoPoint topLeft; 
    GeoPoint bottomRight; 

    public MyBaseImageOverlay(GeoPoint topL, GeoPoint bottomR, Bitmap bmp) { 
     baseBitmap = bmp; 
     topLeft = topL; 
     bottomRight = bottomR; 
    } 

    @Override 
    public void draw(Canvas canvas, MapView mapView, boolean shadow) { 
    if(shadow) { 
      return; 
     } 
     super.draw(canvas, mapView, shadow); 
     // convert bitmap's bounding box into pixels 
     Point top_left = new Point(); 
     mapView.getProjection().toPixels(topLeft, top_left); 
     Point bottom_right = new Point(); 
     mapView.getProjection().toPixels(bottomRight, bottom_right); 
     // Prepare two rectangles (pixels) 
     Rect src = new Rect(0,0,baseBitmap.getWidth() - 1, baseBitmap.getHeight() - 1); 
     Rect dst = new Rect(top_left.x, top_left.y, bottom_right.x,bottom_right.y); 

     // draw bitmap 
     canvas.drawBitmap(baseBitmap, src, dst, null); 
    } 
} 

start.xml:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="match_parent" > 

<Button 
    android:id="@+id/buttonNY" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:layout_alignParentTop="true" 
    android:layout_centerHorizontal="true" 
    android:layout_marginTop="20dp" 
    android:text="NY" /> 

</RelativeLayout> 

activity_main.xml中:

<?xml version="1.0" encoding="utf-8"?> 
<com.google.android.maps.MapView 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/mapview" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:clickable="true" 
    android:apiKey="YOUR_MAP_KEY_HERE" 
/> 

覆盖位图: https://docs.google.com/file/d/0B7GW5mJ5fr3XZFdWYnVBUW45bWM/edit?usp=sharing

回答

1

问题是,你的位图不是~7MB大,你的PNG有多大。它被压缩(除非你使用16bpp色彩空间)。你的图像是2800x1324,所以假设一个正常的ARGB_8888格式,它应该占用约15MB的未压缩。 7为PNG加载,加上15为未压缩的位图...来到22.因此,在这段时间内它将图像解压缩到内存中,它将使用所有这些。

你提到了几个你试过的东西,摆脱了OOM错误(较小的位图,回收),但没有解决“3x”问题。您可以尝试使用Bitmap.Config.RGB_565加载图像。这应该以牺牲质量为代价节省一些内存(应该只使用总共大约15MB),但除此之外,除了你尝试过的东西之外你不能做很多事情。

+1

你摇滚!感谢您的信息...但接下来的问题是为什么这不会有任何问题与4.0.3或2.2(这是我的两个实际的手机),他们工作很好... – Jed

+1

我认为这主要是由于使用3D加速无处不在。如果你根本找不到解决方法,你可以尝试在清单中启用'largeHeap'。一般不建议谷歌,但如果你的应用程序绝对需要它,总比没有好。 – Geobits

+1

再次,谢谢!我正在学习我有很多要学习图形的知识!感谢您的教训! – Jed

相关问题