Я работаю над Galaxy S, и я следовал Displaying Bitmaps Efficiently , чтобы отобразить набор изображений из GridView в отдельной полноэкранной деятельности. Я реализовал FragmentStatePagerAdapter и AsyncTask, но я по-прежнему несут ошибку OutOfMemory, и я больше не знаю, где крушить мою голову! Я также реализовал calculateInSampleSize, поскольку google сказал (он возвращает значения, как 1-2), но если я устанавливаю option.inSampleSize = 16 (для тестирования) все идет правильно! Загружено 8 изображений с идентификатора ресурса, а наибольшее - приблизительно 2560 * 1600.FragmentStatePagerAdapter Fullscreen Растровое изображение из памяти Android
Я знаю, что это очень заданный вопрос, но я не нашел решений ни в google doc, ни на этом сайте.
Спасибо.
Вот мой FullscreenActivity
public class FullScreenActivity extends FragmentActivity{
private ImagePagerAdapter adapter;
private ViewPager viewPager;
int imageWidth;
int imageHeight;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fullscreen);
imageWidth = Utils.getScreenWidth(this);
imageHeight = Utils.getScreenHeight(this);
viewPager = (ViewPager) findViewById(R.id.Viewpager);
Intent i = getIntent();
int position = i.getIntExtra("position", 0);
adapter = new ImagePagerAdapter(getSupportFragmentManager(), ItemList.LISTA_GALLERY_ID.length);
viewPager.setAdapter(adapter);
// displaying selected image first
viewPager.setCurrentItem(position);
}
public void loadBitmap(int resId, ImageView mImageView) {
BitmapWorkerTask task = new BitmapWorkerTask(mImageView);
task.execute(resId);
}
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private int data = 0;
public BitmapWorkerTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
}
// Decode image in background.
@Override
protected Bitmap doInBackground(Integer... params) {
data = params[0];
return Utils.decodeBitmapFromResource(getResources(), data,
imageWidth, imageHeight);
}
// Once complete, see if ImageView is still around and set bitmap.
@Override
protected void onPostExecute(Bitmap bitmap) {
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}
}
А вот мои адаптеры
public class FullScreenImageAdapter {
public static class ImagePagerAdapter extends FragmentStatePagerAdapter {
private final int mSize;
public ImagePagerAdapter(FragmentManager fm, int size) {
super(fm);
mSize = size;
}
@Override
public int getCount() {
return mSize;
}
@Override
public Fragment getItem(int position) {
return ImageDetailFragment.newInstance(position);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object){
super.destroyItem(container, position, object);
}
}
public static class ImageDetailFragment extends Fragment {
private static final String IMAGE_DATA_EXTRA = "resId";
private int mImageNum;
private ImageView mImageView;
static ImageDetailFragment newInstance(int imageNum) {
final ImageDetailFragment f = new ImageDetailFragment();
final Bundle args = new Bundle();
args.putInt(IMAGE_DATA_EXTRA, imageNum);
f.setArguments(args);
return f;
}
// Empty constructor, required as per Fragment docs
public ImageDetailFragment() {}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mImageNum = getArguments() != null ? getArguments().getInt(IMAGE_DATA_EXTRA) : -1;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// image_detail_fragment.xml contains just an ImageView
final View v = inflater.inflate(R.layout.layout_fullscreen_image, container, false);
mImageView = (ImageView) v.findViewById(R.id.imgDisplay);
return v;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (FullScreenActivity.class.isInstance(getActivity())) {
final int resId = ItemList.LISTA_GALLERY_ID[mImageNum];
// Call out to ImageDetailActivity to load the bitmap in a background thread
((FullScreenActivity) getActivity()).loadBitmap(resId, mImageView);
}
}
}
}
LogCat
02-08 19:30:46.680: D/libEGL(12466): loaded /vendor/lib/egl/libGLESv1_CM_POWERVR_SGX540_120.so
02-08 19:30:46.684: D/libEGL(12466): loaded /vendor/lib/egl/libGLESv2_POWERVR_SGX540_120.so
02-08 19:30:46.727: D/OpenGLRenderer(12466): Enabling debug mode 0
02-08 19:30:47.625: I/Choreographer(12466): Skipped 613 frames! The application may be doing too much work on its main thread.
02-08 19:30:50.336: I/Choreographer(12466): Skipped 68 frames! The application may be doing too much work on its main thread.
02-08 19:30:50.934: I/Choreographer(12466): Skipped 32 frames! The application may be doing too much work on its main thread.
02-08 19:31:02.789: D/dalvikvm(12466): threadid=1: still suspended after undo (sc=1 dc=1)
02-08 19:31:02.899: D/dalvikvm(12466): threadid=1: still suspended after undo (sc=1 dc=1)
02-08 19:31:06.043: I/Choreographer(12466): Skipped 186 frames! The application may be doing too much work on its main thread.
02-08 19:31:06.109: D/dalvikvm(12466): threadid=1: still suspended after undo (sc=1 dc=1)
02-08 19:31:06.289: D/dalvikvm(12466): threadid=1: still suspended after undo (sc=1 dc=1)
02-08 19:31:11.266: D/dalvikvm(12466): threadid=1: still suspended after undo (sc=1 dc=1)
02-08 19:31:11.367: D/dalvikvm(12466): threadid=1: still suspended after undo (sc=1 dc=1)
02-08 19:31:11.488: D/dalvikvm(12466): threadid=1: still suspended after undo (sc=1 dc=1)
02-08 19:31:11.590: D/dalvikvm(12466): threadid=1: still suspended after undo (sc=1 dc=1)
02-08 19:31:11.711: D/dalvikvm(12466): threadid=1: still suspended after undo (sc=1 dc=1)
02-08 19:31:11.762: D/dalvikvm(12466): threadid=1: still suspended after undo (sc=1 dc=1)
02-08 19:31:19.406: I/Choreographer(12466): Skipped 456 frames! The application may be doing too much work on its main thread.
02-08 19:31:20.043: I/dalvikvm-heap(12466): Forcing collection of SoftReferences for 6297616-byte allocation
02-08 19:31:20.074: E/dalvikvm-heap(12466): Out of memory on a 6297616-byte allocation.
02-08 19:31:20.074: I/dalvikvm(12466): "AsyncTask #5" prio=5 tid=16 RUNNABLE
02-08 19:31:20.074: I/dalvikvm(12466): | group="main" sCount=0 dsCount=0 obj=0x42400f38 self=0x4e3b0bb8
02-08 19:31:20.074: I/dalvikvm(12466): | sysTid=12523 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=1313770208
02-08 19:31:20.074: I/dalvikvm(12466): | state=R schedstat=(0 0 0) utm=63 stm=3 core=0
02-08 19:31:20.074: I/dalvikvm(12466): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
02-08 19:31:20.082: I/dalvikvm(12466): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:503)
02-08 19:31:20.082: I/dalvikvm(12466): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:356)
02-08 19:31:20.086: I/dalvikvm(12466): at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:379)
02-08 19:31:20.086: I/dalvikvm(12466): at com.example.parrucchieriprova.helper.Utils.decodeBitmapFromResource(Utils.java:26)
02-08 19:31:20.086: I/dalvikvm(12466): at com.example.parrucchieriprova.FullScreenActivity$BitmapWorkerTask.doInBackground(FullScreenActivity.java:63)
02-08 19:31:20.086: I/dalvikvm(12466): at com.example.parrucchieriprova.FullScreenActivity$BitmapWorkerTask.doInBackground(FullScreenActivity.java:1)
02-08 19:31:20.094: I/dalvikvm(12466): at android.os.AsyncTask$2.call(AsyncTask.java:287)
02-08 19:31:20.106: I/dalvikvm(12466): at java.util.concurrent.FutureTask.run(FutureTask.java:234)
02-08 19:31:20.106: I/dalvikvm(12466): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
02-08 19:31:20.106: I/dalvikvm(12466): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
02-08 19:31:20.106: I/dalvikvm(12466): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
02-08 19:31:20.109: I/dalvikvm(12466): at java.lang.Thread.run(Thread.java:841)
02-08 19:31:20.109: D/skia(12466): --- allocation failed for scaled bitmap
02-08 19:31:20.195: D/dalvikvm(12466): threadid=16: still suspended after undo (sc=1 dc=1)
02-08 19:31:23.082: D/dalvikvm(12466): threadid=1: still suspended after undo (sc=1 dc=1)
02-08 19:31:23.082: W/dalvikvm(12466): threadid=16: thread exiting with uncaught exception (group=0x418d47c0)
02-08 19:31:23.117: E/AndroidRuntime(12466): FATAL EXCEPTION: AsyncTask #5
02-08 19:31:23.117: E/AndroidRuntime(12466): java.lang.RuntimeException: An error occured while executing doInBackground()
02-08 19:31:23.117: E/AndroidRuntime(12466): at android.os.AsyncTask$3.done(AsyncTask.java:299)
02-08 19:31:23.117: E/AndroidRuntime(12466): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
02-08 19:31:23.117: E/AndroidRuntime(12466): at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
02-08 19:31:23.117: E/AndroidRuntime(12466): at java.util.concurrent.FutureTask.run(FutureTask.java:239)
02-08 19:31:23.117: E/AndroidRuntime(12466): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
02-08 19:31:23.117: E/AndroidRuntime(12466): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
02-08 19:31:23.117: E/AndroidRuntime(12466): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
02-08 19:31:23.117: E/AndroidRuntime(12466): at java.lang.Thread.run(Thread.java:841)
02-08 19:31:23.117: E/AndroidRuntime(12466): Caused by: java.lang.OutOfMemoryError
02-08 19:31:23.117: E/AndroidRuntime(12466): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
02-08 19:31:23.117: E/AndroidRuntime(12466): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:503)
02-08 19:31:23.117: E/AndroidRuntime(12466): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:356)
02-08 19:31:23.117: E/AndroidRuntime(12466): at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:379)
02-08 19:31:23.117: E/AndroidRuntime(12466): at com.example.parrucchieriprova.helper.Utils.decodeBitmapFromResource(Utils.java:26)
02-08 19:31:23.117: E/AndroidRuntime(12466): at com.example.parrucchieriprova.FullScreenActivity$BitmapWorkerTask.doInBackground(FullScreenActivity.java:63)
02-08 19:31:23.117: E/AndroidRuntime(12466): at com.example.parrucchieriprova.FullScreenActivity$BitmapWorkerTask.doInBackground(FullScreenActivity.java:1)
02-08 19:31:23.117: E/AndroidRuntime(12466): at android.os.AsyncTask$2.call(AsyncTask.java:287)
02-08 19:31:23.117: E/AndroidRuntime(12466): at java.util.concurrent.FutureTask.run(FutureTask.java:234)
02-08 19:31:23.117: E/AndroidRuntime(12466): ... 4 more
02-08 19:31:26.383: I/Process(12466): Sending signal. PID: 12466 SIG: 9
02-08 19:31:27.442: D/libEGL(12526): loaded /vendor/lib/egl/libEGL_POWERVR_SGX540_120.so
02-08 19:31:27.461: D/libEGL(12526): loaded /vendor/lib/egl/libGLESv1_CM_POWERVR_SGX540_120.so
02-08 19:31:27.469: D/libEGL(12526): loaded /vendor/lib/egl/libGLESv2_POWERVR_SGX540_120.so
02-08 19:31:27.512: D/OpenGLRenderer(12526): Enabling debug mode 0
02-08 19:31:28.672: I/Choreographer(12526): Skipped 99 frames! The application may be doing too much work on its main thread.
02-08 19:31:46.328: I/dalvikvm-heap(12526): Forcing collection of SoftReferences for 15369616-byte allocation
02-08 19:31:46.356: E/dalvikvm-heap(12526): Out of memory on a 15369616-byte allocation.
02-08 19:31:46.356: I/dalvikvm(12526): "AsyncTask #1" prio=5 tid=12 RUNNABLE
02-08 19:31:46.356: I/dalvikvm(12526): | group="main" sCount=0 dsCount=0 obj=0x423a9840 self=0x4e6bb9e8
02-08 19:31:46.356: I/dalvikvm(12526): | sysTid=12540 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=1234453912
02-08 19:31:46.356: I/dalvikvm(12526): | state=R schedstat=(0 0 0) utm=35 stm=1 core=0
02-08 19:31:46.356: I/dalvikvm(12526): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
02-08 19:31:46.359: I/dalvikvm(12526): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:503)
02-08 19:31:46.359: I/dalvikvm(12526): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:356)
02-08 19:31:46.359: I/dalvikvm(12526): at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:379)
02-08 19:31:46.359: I/dalvikvm(12526): at com.example.parrucchieriprova.helper.Utils.decodeBitmapFromResource(Utils.java:26)
02-08 19:31:46.359: I/dalvikvm(12526): at com.example.parrucchieriprova.FullScreenActivity$BitmapWorkerTask.doInBackground(FullScreenActivity.java:63)
02-08 19:31:46.359: I/dalvikvm(12526): at com.example.parrucchieriprova.FullScreenActivity$BitmapWorkerTask.doInBackground(FullScreenActivity.java:1)
02-08 19:31:46.359: I/dalvikvm(12526): at android.os.AsyncTask$2.call(AsyncTask.java:287)
02-08 19:31:46.359: I/dalvikvm(12526): at java.util.concurrent.FutureTask.run(FutureTask.java:234)
02-08 19:31:46.359: I/dalvikvm(12526): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
02-08 19:31:46.359: I/dalvikvm(12526): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
02-08 19:31:46.359: I/dalvikvm(12526): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
02-08 19:31:46.359: I/dalvikvm(12526): at java.lang.Thread.run(Thread.java:841)
02-08 19:31:46.363: D/skia(12526): --- allocation failed for scaled bitmap
02-08 19:31:46.363: W/dalvikvm(12526): threadid=12: thread exiting with uncaught exception (group=0x418d47c0)
02-08 19:31:46.371: E/AndroidRuntime(12526): FATAL EXCEPTION: AsyncTask #1
02-08 19:31:46.371: E/AndroidRuntime(12526): java.lang.RuntimeException: An error occured while executing doInBackground()
02-08 19:31:46.371: E/AndroidRuntime(12526): at android.os.AsyncTask$3.done(AsyncTask.java:299)
02-08 19:31:46.371: E/AndroidRuntime(12526): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
02-08 19:31:46.371: E/AndroidRuntime(12526): at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
02-08 19:31:46.371: E/AndroidRuntime(12526): at java.util.concurrent.FutureTask.run(FutureTask.java:239)
02-08 19:31:46.371: E/AndroidRuntime(12526): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
02-08 19:31:46.371: E/AndroidRuntime(12526): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
02-08 19:31:46.371: E/AndroidRuntime(12526): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
02-08 19:31:46.371: E/AndroidRuntime(12526): at java.lang.Thread.run(Thread.java:841)
02-08 19:31:46.371: E/AndroidRuntime(12526): Caused by: java.lang.OutOfMemoryError
02-08 19:31:46.371: E/AndroidRuntime(12526): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
02-08 19:31:46.371: E/AndroidRuntime(12526): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:503)
02-08 19:31:46.371: E/AndroidRuntime(12526): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:356)
02-08 19:31:46.371: E/AndroidRuntime(12526): at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:379)
02-08 19:31:46.371: E/AndroidRuntime(12526): at com.example.parrucchieriprova.helper.Utils.decodeBitmapFromResource(Utils.java:26)
02-08 19:31:46.371: E/AndroidRuntime(12526): at com.example.parrucchieriprova.FullScreenActivity$BitmapWorkerTask.doInBackground(FullScreenActivity.java:63)
02-08 19:31:46.371: E/AndroidRuntime(12526): at com.example.parrucchieriprova.FullScreenActivity$BitmapWorkerTask.doInBackground(FullScreenActivity.java:1)
02-08 19:31:46.371: E/AndroidRuntime(12526): at android.os.AsyncTask$2.call(AsyncTask.java:287)
02-08 19:31:46.371: E/AndroidRuntime(12526): at java.util.concurrent.FutureTask.run(FutureTask.java:234)
02-08 19:31:46.371: E/AndroidRuntime(12526): ... 4 more
02-08 19:31:55.117: I/Process(12526): Sending signal. PID: 12526 SIG: 9
02-08 19:32:07.188: D/libEGL(12554): loaded /vendor/lib/egl/libEGL_POWERVR_SGX540_120.so
02-08 19:32:07.195: D/libEGL(12554): loaded /vendor/lib/egl/libGLESv1_CM_POWERVR_SGX540_120.so
02-08 19:32:07.203: D/libEGL(12554): loaded /vendor/lib/egl/libGLESv2_POWERVR_SGX540_120.so
02-08 19:32:07.246: D/OpenGLRenderer(12554): Enabling debug mode 0
02-08 19:32:08.067: I/Choreographer(12554): Skipped 53 frames! The application may be doing too much work on its main thread.
02-08 19:32:27.145: I/Choreographer(12554): Skipped 51 frames! The application may be doing too much work on its main thread.
02-08 19:33:08.199: I/Choreographer(12554): Skipped 48 frames! The application may be doing too much work on its main thread.
02-08 19:33:43.828: I/Choreographer(12554): Skipped 57 frames! The application may be doing too much work on its main thread.
02-08 19:34:39.531: I/Choreographer(12554): Skipped 64 frames! The application may be doing too much work on its main thread.
02-08 19:35:06.149: I/Choreographer(12554): Skipped 49 frames! The application may be doing too much work on its main thread.
02-08 19:35:08.539: I/Choreographer(12554): Skipped 53 frames! The application may be doing too much work on its main thread.
02-08 19:35:12.774: I/Choreographer(12554): Skipped 47 frames! The application may be doing too much work on its main thread.
Почему вы используете FragmentStatePagerAdapter? Когда вы имеете дело с изображениями, сохранение больших растровых изображений как части фрагментов, поддерживаемых FragmentStatePagerAdapter, заставит их оставаться в памяти, пока активность не будет уничтожена. Попробуйте использовать только FragmentPagerAdapter. –
Из-за этого «Эта версия пейджера более полезна, когда имеется большое количество страниц, больше похоже на просмотр списка. Когда страницы не видны пользователю, весь их фрагмент может быть уничтожен, сохраняя сохраненное состояние от этого фрагмента, что позволяет пейджеру удерживать гораздо меньше памяти, связанной с каждой посещенной страницей, по сравнению с FragmentPagerAdapter за счет потенциально большего количества накладных расходов при переключении между страницами ». – user3287734
Но у вас есть ограниченное количество памяти для воспроизведения. Вы не можете помещать так много больших растровых изображений (8 из них) в оперативную память все время, поскольку оно неизбежно вызывает ошибку OutOfMemory. –