更新(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
你搖滾!感謝您的信息...但接下來的問題是爲什麼這不會有任何問題與4.0.3或2.2(這是我的兩個實際的手機),他們工作很好... – Jed
我認爲這主要是由於使用3D加速無處不在。如果你根本找不到解決方法,你可以嘗試在清單中啓用'largeHeap'。一般不建議谷歌,但如果你的應用程序絕對需要它,總比沒有好。 – Geobits
再次,謝謝!我正在學習我有很多要學習圖形的知識!感謝您的教訓! – Jed