我有两项活动。在开始活动中有小图像。点击其中的每一个,然后在ViewPager
处使用图库打开其他活动。
当打开图库时,它可以完美地滑动图像而没有任何问题。
但是当我回到开始活动并重新打开图库时,应用程序崩溃了
java.lang.OutOfMemoryError
位图大小超过vm预算
我尝试重新调整图片大小,将图片缩小,但没有用。它也崩溃了一会儿。
我认为当Gallery和所有图像的活动没有被销毁时。它有内存泄漏。
对于图库,我使用AndroidTouchGallery
:link
这是使用此代码的示例应用:workspace link on GoogleDrive
我的代码。 开始活动
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayList<String> list_big_images = new ArrayList<String>();
list_big_images.add("http://www.oa.edu.ua/assets/images/n/2013/small/evropeyska_misiya1_s.jpg");
list_big_images.add("http://www.oa.edu.ua/assets/images/n/2013/small/evropeyska_misiya2_s.jpg");
list_big_images.add("http://www.oa.edu.ua/assets/images/n/2013/small/evropeyska_misiya3_s.jpg");
ArrayList<String> list_big_images_big = new ArrayList<String>();
list_big_images_big.add("http://www.oa.edu.ua/assets/images/n/2013/big/evropeyska_misiya1_b.jpg");
list_big_images_big.add("http://www.oa.edu.ua/assets/images/n/2013/big/evropeyska_misiya2_b.jpg");
list_big_images_big.add("http://www.oa.edu.ua/assets/images/n/2013/big/evropeyska_misiya3_b.jpg");
//get Screen size
int width; //Display width
int height; //Display height
if ( Integer.valueOf(android.os.Build.VERSION.SDK_INT) > 13 ) {
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
width = size.x;
height = size.y;
} else {
Display display = getWindowManager().getDefaultDisplay();
width = display.getWidth();
height = display.getHeight();
}
ImageView[] imageViewArray = new ImageView[list_big_images.size()];
for (int i = 0; i<list_big_images.size(); i++)
try {
String url = list_big_images.get(i);
//url_img_small.add(text);
// Let's create the missing ImageView
imageViewArray[i] = new ImageView(MainActivity.this);
// Now the layout parameters, these are a little tricky at first
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(width/3, width/3);
imageViewArray[i].setScaleType(ImageView.ScaleType.FIT_XY);
imageViewArray[i].setId(i + 1); // BELOW id 0 doesn't work
imageViewArray[i].setPadding(0, 5, 5, 0);
if (i > 0) {
if (i % 3 == 0){
params.addRule(RelativeLayout.BELOW, imageViewArray[i - 3].getId());
}
else {
params.addRule(RelativeLayout.RIGHT_OF, imageViewArray[i - 1].getId());
if (i>2)
params.addRule(RelativeLayout.BELOW, imageViewArray[i - 3].getId());
};
}
Drawable drawable = grabImageFromUrl(url);
imageViewArray[i].setImageDrawable(drawable);
final ArrayList<String> list_big_images_big2 = list_big_images_big;
final int pos = i;
imageViewArray[i].setOnClickListener( new OnClickListener()
{
@Override
public void onClick(View v) {
System.out.println(v.getId());
Intent intent = new Intent(v.getContext(), Full_Image_Activity.class);
intent.putExtra("ArrayImgBig", list_big_images_big2);
intent.putExtra("pos", pos+1);
startActivityForResult(intent, 0);
}
});
// Let's get the root layout and add our ImageView
RelativeLayout layout = (RelativeLayout) findViewById(R.id.moreImages);
layout.addView(imageViewArray[i], params);
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//load Image from Url
private Drawable grabImageFromUrl(String url) throws Exception {
return Drawable.createFromStream(
(InputStream) new URL(url).getContent(), "src");
}
}
它与画廊的活动
public class Full_Image_Activity extends Activity {
ArrayList <String> ArrayImgBig = null;
int id_news;
private GalleryViewPager mViewPager;
int pos ; //Picture Position
UrlPagerAdapter pagerAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_full__image);
ArrayImgBig = getIntent().getExtras().getStringArrayList("ArrayImgBig");
pos = getIntent().getExtras().getInt("pos");
UrlPagerAdapter pagerAdapter = new UrlPagerAdapter(Full_Image_Activity.this, ArrayImgBig);
pagerAdapter.setOnItemChangeListener(new OnItemChangeListener()
{
@Override
public void onItemChange(int currentPosition)
{
Toast.makeText(Full_Image_Activity.this, "Current item is " + currentPosition, Toast.LENGTH_SHORT).show();
}
});
mViewPager = (GalleryViewPager)findViewById(R.id.viewer);
mViewPager.setOffscreenPageLimit(3);
mViewPager.setAdapter(pagerAdapter);
mViewPager.setCurrentItem(pos);
}
@Override
public void onBackPressed() {
this.finish();
}
@Override
public void onDestroy() {
super.onDestroy();
pagerAdapter = null;
mViewPager = null;
System.gc();
}
}
我使用方法onDestoy
。但它没有帮助。一切都是一样的。
日志:
11-27 15:39:59.239: I/System.out(471): 1
11-27 15:40:00.248: D/dalvikvm(471): GC_EXTERNAL_ALLOC freed 1638K, 48% free 4736K/9031K, external 15372K/16229K, paused 116ms
11-27 15:40:00.879: D/dalvikvm(471): GC_EXTERNAL_ALLOC freed 35K, 48% free 4742K/9031K, external 17773K/18518K, paused 100ms
11-27 15:40:02.519: I/dalvikvm(471): Jit: resizing JitTable from 2048 to 4096
11-27 15:40:04.959: W/KeyCharacterMap(471): No keyboard for id 0
11-27 15:40:04.959: W/KeyCharacterMap(471): Using default keymap: /system/usr/keychars/qwerty.kcm.bin
11-27 15:40:05.159: D/dalvikvm(471): GC_EXPLICIT freed 155K, 49% free 4654K/9031K, external 20410K/21124K, paused 111ms
11-27 15:40:05.738: D/dalvikvm(471): GC_EXPLICIT freed 3K, 49% free 4652K/9031K, external 20410K/21124K, paused 223ms
11-27 15:40:10.703: I/System.out(471): 2
11-27 15:40:11.748: D/dalvikvm(471): GC_EXTERNAL_ALLOC freed 43K, 48% free 4754K/9031K, external 20410K/21124K, paused 106ms
11-27 15:40:11.998: D/dalvikvm(471): GC_EXTERNAL_ALLOC freed 4K, 48% free 4780K/9031K, external 23046K/23760K, paused 112ms
11-27 15:40:12.048: E/dalvikvm-heap(471): 1334000-byte external allocation too large for this process.
11-27 15:40:12.208: E/GraphicsJNI(471): VM won't let us allocate 1334000 bytes
11-27 15:40:12.208: D/dalvikvm(471): GC_FOR_MALLOC freed 0K, 48% free 4780K/9031K, external 23046K/23760K, paused 87ms
11-27 15:40:12.229: D/skia(471): --- decoder->decode returned false
11-27 15:40:12.238: W/dalvikvm(471): threadid=23: thread exiting with uncaught exception (group=0x40015560)
11-27 15:40:12.248: E/AndroidRuntime(471): FATAL EXCEPTION: AsyncTask #5
11-27 15:40:12.248: E/AndroidRuntime(471): java.lang.RuntimeException: An error occured while executing doInBackground()
11-27 15:40:12.248: E/AndroidRuntime(471): at android.os.AsyncTask$3.done(AsyncTask.java:200)
11-27 15:40:12.248: E/AndroidRuntime(471): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
11-27 15:40:12.248: E/AndroidRuntime(471): at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
11-27 15:40:12.248: E/AndroidRuntime(471): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
11-27 15:40:12.248: E/AndroidRuntime(471): at java.util.concurrent.FutureTask.run(FutureTask.java:138)
11-27 15:40:12.248: E/AndroidRuntime(471): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
11-27 15:40:12.248: E/AndroidRuntime(471): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
11-27 15:40:12.248: E/AndroidRuntime(471): at java.lang.Thread.run(Thread.java:1019)
11-27 15:40:12.248: E/AndroidRuntime(471): Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
11-27 15:40:12.248: E/AndroidRuntime(471): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
11-27 15:40:12.248: E/AndroidRuntime(471): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:470)
11-27 15:40:12.248: E/AndroidRuntime(471): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:525)
11-27 15:40:12.248: E/AndroidRuntime(471): at ru.truba.touchgallery.TouchView.UrlTouchImageView$ImageLoadTask.doInBackground(UrlTouchImageView.java:102)
11-27 15:40:12.248: E/AndroidRuntime(471): at ru.truba.touchgallery.TouchView.UrlTouchImageView$ImageLoadTask.doInBackground(UrlTouchImageView.java:1)
11-27 15:40:12.248: E/AndroidRuntime(471): at android.os.AsyncTask$2.call(AsyncTask.java:185)
11-27 15:40:12.248: E/AndroidRuntime(471): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
11-27 15:40:12.248: E/AndroidRuntime(471): ... 4 more
答案 0 :(得分:0)
将您的onDestroy编辑为以下内容:
@Override
public void onDestroy() {
pagerAdapter = null;
mViewPager = null;
System.gc();
super.onDestroy();
}
或将代码放入onPause()
答案 1 :(得分:0)
您可以在viewpager适配器中检查是否覆盖了destroyItem。这将在屏幕上不再显示时删除视图,从而释放为该图像分配的内存。
示例:
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
我还建议你使用像Picasso或通用图像加载器这样的图像加载器来异步加载ui线程的图像,并为你处理它们在内存中的分配,这样你就不会出现内存异常...