包含ImageViews的ViewPager的java.lang.OutOfMemoryError

时间:2016-07-17 17:40:34

标签: android android-fragments android-viewpager imageview out-of-memory

我的应用中有ViewPager,其中包含8个片段。 一些片段包含10个图像,有时在片段之间交换应用程序崩溃,因为java.lang.OutOfMemoryError

我不知道如何避免这个错误我觉得它发生是因为ViewPager和大量图片请帮我解决这个问题。

谢谢!

在MainActivity onCreate方法中:

ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
    setupViewPager(viewPager);

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
    if (tabLayout != null) {
        tabLayout.setupWithViewPager(viewPager);
    }

setupViewPager():

private void setupViewPager(ViewPager viewPager) {
    ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());

        adapter.addFragment(new S1(), getString(R.string.stage1));
        adapter.addFragment(new S2(), getString(R.string.stage2));
        adapter.addFragment(new S3(), getString(R.string.stage3));
        adapter.addFragment(new S4(), getString(R.string.stage4));
        adapter.addFragment(new S5(), getString(R.string.stage5));
        adapter.addFragment(new S6(), getString(R.string.stage6));
        adapter.addFragment(new S7(), getString(R.string.stage7));
        adapter.addFragment(new S8(), getString(R.string.stage8));

    viewPager.setAdapter(adapter);
}

类ViewPagerAdapter:

class ViewPagerAdapter extends FragmentPagerAdapter {
    private final List<Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();

    public ViewPagerAdapter(FragmentManager manager) {
        super(manager);
    }

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }

    @Override
    public int getCount() {
        return mFragmentList.size();
    }

    public void addFragment(Fragment fragment, String title) {
        mFragmentList.add(fragment);
        mFragmentTitleList.add(title);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitleList.get(position);
    }
}

Fragemt S1:

public class S1 extends Fragment {

public S1() {
    // Required empty public constructor
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    View rootView = inflater.inflate(R.layout.fragment_s1, container, false);

    ImageView image1 = (ImageView)rootView.findViewById(R.id.imageView_S0P1);
    ImageView image2 = (ImageView)rootView.findViewById(R.id.imageView_S0P2);
    ImageView image3 = (ImageView)rootView.findViewById(R.id.imageView_S0P3);
    ImageView image4 = (ImageView)rootView.findViewById(R.id.imageView_S0P4);
    ImageView image5 = (ImageView)rootView.findViewById(R.id.imageView_S0P5);
    ImageView image6 = (ImageView)rootView.findViewById(R.id.imageView_S0P6);
    ImageView image7 = (ImageView)rootView.findViewById(R.id.imageView_S0P7);
    ImageView image8 = (ImageView)rootView.findViewById(R.id.imageView_S0P8);
    ImageView image9 = (ImageView)rootView.findViewById(R.id.imageView_S0P9);
    ImageView image10 = (ImageView)rootView.findViewById(R.id.imageView_S0P10);

    image1.setImageResource(R.drawable.s0p1);
    image2.setImageResource(R.drawable.s0p2);
    image3.setImageResource(R.drawable.s0p3);
    image4.setImageResource(R.drawable.s0p4);
    image5.setImageResource(R.drawable.s0p5);
    image6.setImageResource(R.drawable.s0p6);
    image7.setImageResource(R.drawable.s0p7);
    image8.setImageResource(R.drawable.s0p8);
    image9.setImageResource(R.drawable.s0p9);
    image10.setImageResource(R.drawable.s0p10);

    return rootView;
 }
}

fragment_s1.xml:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/scrollView_intro"
tools:context="appinventor.ai_itiel_maimon.Rubiks_cube.s1">

 <LinearLayout
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical">

     //TextView

     <ImageView
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:adjustViewBounds="true"
         android:id="@+id/imageView_S0P1"
         android:scaleType="fitCenter"
         android:contentDescription="@string/image_description" />

     <ImageView
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:adjustViewBounds="true"
         android:id="@+id/imageView_S0P2"
         android:scaleType="fitCenter"
         android:contentDescription="@string/image_description" />

     //TextView

     //TextView

     <ImageView
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:adjustViewBounds="true"
         android:id="@+id/imageView_S0P3"
         android:scaleType="fitCenter"
         android:contentDescription="@string/image_description" />

     <ImageView
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:adjustViewBounds="true"
         android:id="@+id/imageView_S0P4"
         android:scaleType="fitCenter"
         android:contentDescription="@string/image_description" />

     //TextView

     <ImageView
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:adjustViewBounds="true"
         android:id="@+id/imageView_S0P5"
         android:scaleType="fitCenter"
         android:contentDescription="@string/image_description" />

     //TextView

     <ImageView
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:adjustViewBounds="true"
         android:id="@+id/imageView_S0P6"
         android:scaleType="fitCenter"
         android:contentDescription="@string/image_description" />

     <ImageView
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:adjustViewBounds="true"
         android:id="@+id/imageView_S0P7"
         android:scaleType="fitCenter"
         android:contentDescription="@string/image_description" />

     //TextView

     //TextView

     <ImageView
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:adjustViewBounds="true"
         android:id="@+id/imageView_S0P8"
         android:scaleType="fitCenter"
         android:contentDescription="@string/image_description" />

     <ImageView
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:adjustViewBounds="true"
         android:id="@+id/imageView_S0P9"
         android:scaleType="fitCenter"
         android:contentDescription="@string/image_description" />

     //TextView

     <ImageView
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:adjustViewBounds="true"
         android:id="@+id/imageView_S0P10"
         android:scaleType="fitCenter"
         android:contentDescription="@string/image_description" />

 </LinearLayout>

</ScrollView>

logcat的:

07-17 20:58:31.334 30652-30652/appinventor.ai_itiel_maimon.Rubiks_cube E/AndroidRuntime: FATAL EXCEPTION: main
Process: appinventor.ai_itiel_maimon.Rubiks_cube, PID: 30652
java.lang.OutOfMemoryError: Failed to allocate a 8876812 byte allocation with 7873968 free bytes and 7MB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:856)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:675)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:2228)
at android.content.res.Resources.loadDrawableForCookie(Resources.java:4211)
at android.content.res.Resources.loadDrawable(Resources.java:4085)
at android.content.res.Resources.getDrawable(Resources.java:2005)
at android.content.res.Resources.getDrawable(Resources.java:1987)
at android.support.v7.widget.ResourcesWrapper.getDrawable(ResourcesWrapper.java:133)
at android.content.Context.getDrawable(Context.java:464)
at android.support.v4.content.ContextCompatApi21.getDrawable(ContextCompatApi21.java:26)
at android.support.v4.content.ContextCompat.getDrawable(ContextCompat.java:352)
at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:193)
at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:181)
at android.support.v7.widget.AppCompatImageHelper.setImageResource(AppCompatImageHelper.java:72)
at android.support.v7.widget.AppCompatImageView.setImageResource(AppCompatImageView.java:71)
at appinventor.ai_itiel_maimon.Rubiks_cube.S7.onCreateView(S7.java:28)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2074)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
at android.support.v4.app.FragmentManagerImpl.attachFragment(FragmentManager.java:1464)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:748)
at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:1632)
at android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:637)
at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:143)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1235)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:666)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:628)
at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:609)
at android.support.design.widget.TabLayout$ViewPagerOnTabSelectedListener.onTabSelected(TabLayout.java:2168)
at android.support.design.widget.TabLayout.dispatchTabSelected(TabLayout.java:1157)
at android.support.design.widget.TabLayout.selectTab(TabLayout.java:1151)
at android.support.design.widget.TabLayout.selectTab(TabLayout.java:1124)
at android.support.design.widget.TabLayout$Tab.select(TabLayout.java:1419)
at android.support.design.widget.TabLayout$TabView.performClick(TabLayout.java:1524)
at android.view.View$PerformClick.run(View.java:22526)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7229)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

修改

我使用位图加载图片,它给了我java.lang.OutOfMemoryError: Failed to allocate a 8876812 byte allocation with 7889984 free bytes and 7MB until OOM

这是我使用的代码:

片段S1:

public class Intro extends S1 {

public S1 () {
    // Required empty public constructor
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    View rootView = inflater.inflate(R.layout.fragment_s1, container, false);

    final int IMAGE_WIDTH  = 500;
    final int IMAGE_HEIGHT  = 500;

    ImageView image1 = (ImageView)rootView.findViewById(R.id.imageView_S0P1);
    ImageView image2 = (ImageView)rootView.findViewById(R.id.imageView_S0P2);
    ImageView image3 = (ImageView)rootView.findViewById(R.id.imageView_S0P3);
    ImageView image4 = (ImageView)rootView.findViewById(R.id.imageView_S0P4);
    ImageView image5 = (ImageView)rootView.findViewById(R.id.imageView_S0P5);
    ImageView image6 = (ImageView)rootView.findViewById(R.id.imageView_S0P6);
    ImageView image7 = (ImageView)rootView.findViewById(R.id.imageView_S0P7);
    ImageView image8 = (ImageView)rootView.findViewById(R.id.imageView_S0P8);
    ImageView image9 = (ImageView)rootView.findViewById(R.id.imageView_S0P9);
    ImageView image10 = (ImageView)rootView.findViewById(R.id.imageView_S0P10);

    image1.setImageBitmap(
            decodeSampledBitmapFromResource(getResources(), R.drawable.s0p1, IMAGE_WIDTH, IMAGE_HEIGHT));
    image2.setImageBitmap(
            decodeSampledBitmapFromResource(getResources(), R.drawable.s0p2, IMAGE_WIDTH, IMAGE_HEIGHT));
    image3.setImageBitmap(
            decodeSampledBitmapFromResource(getResources(), R.drawable.s0p3, IMAGE_WIDTH, IMAGE_HEIGHT));
    image4.setImageBitmap(
            decodeSampledBitmapFromResource(getResources(), R.drawable.s0p4, IMAGE_WIDTH, IMAGE_HEIGHT));
    image5.setImageBitmap(
            decodeSampledBitmapFromResource(getResources(), R.drawable.s0p5, IMAGE_WIDTH, IMAGE_HEIGHT));
    image6.setImageBitmap(
            decodeSampledBitmapFromResource(getResources(), R.drawable.s0p6, IMAGE_WIDTH, IMAGE_HEIGHT));
    image7.setImageBitmap(
            decodeSampledBitmapFromResource(getResources(), R.drawable.s0p7, IMAGE_WIDTH, IMAGE_HEIGHT));
    image8.setImageBitmap(
            decodeSampledBitmapFromResource(getResources(), R.drawable.s0p8, IMAGE_WIDTH, IMAGE_HEIGHT));
    image9.setImageBitmap(
            decodeSampledBitmapFromResource(getResources(), R.drawable.s0p9, IMAGE_WIDTH, IMAGE_HEIGHT));
    image10.setImageBitmap(
            decodeSampledBitmapFromResource(getResources(), R.drawable.s0p10, IMAGE_WIDTH, IMAGE_HEIGHT));

    // Inflate the layout for this fragment
    return rootView;
}

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
                                                     int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}

public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) >= reqHeight
                && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}
}

3 个答案:

答案 0 :(得分:0)

请考虑FragmentStatePagerAdapter而不是FragmentPagerAdapter,并在每个片段中使用RecyclerView而不是使用许多图片进行布局。这将减少内存使用量,从而解决您的OOM问题。

答案 1 :(得分:0)

根据您想要达到的目标,有几种可能性:

1

你可以减少

final int IMAGE_WIDTH  = 500;
final int IMAGE_HEIGHT  = 500;

final int IMAGE_WIDTH  = 250;
final int IMAGE_HEIGHT  = 250;

通过这种方式,您可以将图像的内存占用减少4倍。

2

添加

android:largeHeap="true"

到你的清单(见application tag documentation)。这将为您提供更多的堆空间,但不保证可以在所有设备上运行。

3

RGB_565

中使用BitmapFactory.Options
options.inPreferredConfig = Bitmap.Config.RGB_565;

Bitmap.Config 当你不需要alpha时,将你的位图缩小到一半大小。这会影响图像质量。

答案 2 :(得分:0)

我通过使用Fresco库来加载图像来解决这个问题。这非常有帮助! http://frescolib.org