我的应用中有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;
}
}
答案 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