java - 布局膨胀期间由 OutOfMemoryError 引起的 InflateException

标签 java android out-of-memory

我正在尝试实现谷歌的选项卡 SlidingTabLayout。选项卡将显示在屏幕的下半部分,而上半部分包含普通的文本和 ImageView 。我知道 View 实现中有问题,但我无法准确地弄清楚。

对于 java.lang.OutOfMemoryError,我尝试将 RAM 值设置为等于 HAXM 值,并将 VM 堆增加到 256MB,但它仍然给出相同的错误。

错误:

    08-24 15:56:32.048    2032-2032/com.company.company.testapp E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com..company.company.testapp, PID: 2032
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com..company.company.testapp/com..company.company.testapp.ViewProfile}: android.view.InflateException: Binary XML file line #9: Error inflating class <unknown>
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
            at android.app.ActivityThread.access$800(ActivityThread.java:144)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
     Caused by: android.view.InflateException: Binary XML file line #9: Error inflating class <unknown>
            at android.view.LayoutInflater.createView(LayoutInflater.java:633)
            at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:55)
            at android.view.LayoutInflater.onCreateView(LayoutInflater.java:682)
            at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:741)
            at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
            at android.support.v7.app.ActionBarActivityDelegateBase.setContentView(ActionBarActivityDelegateBase.java:240)
            at android.support.v7.app.ActionBarActivity.setContentView(ActionBarActivity.java:102)
            at com.aldoshik.rewardtrunk.rewardtrunk5.ViewProfile.onCreate(ViewProfile.java:34)
            at android.app.Activity.performCreate(Activity.java:5933)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
            at android.app.ActivityThread.access$800(ActivityThread.java:144)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
     Caused by: java.lang.reflect.InvocationTargetException
            at java.lang.reflect.Constructor.newInstance(Native Method)
            at java.lang.reflect.Constructor.newInstance(Constructor.java:288)
            at android.view.LayoutInflater.createView(LayoutInflater.java:607)
            at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:55)
            at android.view.LayoutInflater.onCreateView(LayoutInflater.java:682)
            at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:741)
            at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
            at android.support.v7.app.ActionBarActivityDelegateBase.setContentView(ActionBarActivityDelegateBase.java:240)
            at android.support.v7.app.ActionBarActivity.setContentView(ActionBarActivity.java:102)
            at com.company.company.testapp.ViewProfile.onCreate(ViewProfile.java:34)
            at android.app.Activity.performCreate(Activity.java:5933)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
            at android.app.ActivityThread.access$800(ActivityThread.java:144)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
     Caused by: java.lang.OutOfMemoryError: Failed to allocate a 1638998616 byte allocation with 4194304 free bytes and 246MB until OOM
            at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
            at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
            at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:609)
            at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:444)
            at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:973)
            at android.content.res.Resources.loadDrawableForCookie(Resources.java:2423)
            at android.content.res.Resources.loadDrawable(Resources.java:2330)
            at android.content.res.TypedArray.getDrawable(TypedArray.java:749)
            at android.view.View.<init>(View.java:3730)
            at android.view.ViewGroup.<init>(ViewGroup.java:491)
            at android.widget.RelativeLayout.<init>(RelativeLayout.java:248)
            at android.widget.RelativeLayout.<init>(RelativeLayout.java:244)
            at android.widget.RelativeLayout.<init>(RelativeLayout.java:240)
            at java.lang.reflect.Constructor.newInstance(Native Method)
            at java.lang.reflect.Constructor.newInstance(Constructor.java:288)
            at android.view.LayoutInflater.createView(LayoutInflater.java:607)
            at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:55)
            at android.view.LayoutInflater.onCreateView(LayoutInflater.java:682)
            at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:741)
            at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
            at android.support.v7.app.ActionBarActivityDelegateBase.setContentView(ActionBarActivityDelegateBase.java:240)
            at android.support.v7.app.ActionBarActivity.setContentView(ActionBarActivity.java:102)
            at com.company.company.testapp.ViewProfile.onCreate(ViewProfile.java:34)
            at android.app.Activity.performCreate(Activity.java:5933)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
            at android.app.ActivityThread.access$800(ActivityThread.java:144)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

XML 布局:

    <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff">

    <RelativeLayout 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"
    tools:context="com.company.company.testapp.ViewProfile"
        android:background="@drawable/profile_page_background_blur">

    <include layout="@layout/app_bar"
        android:id="@+id/app_bar_profile"/>

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/app_bar_profile"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        android:id="@+id/profile_above"
        android:orientation="vertical"
        android:layout_gravity="center_vertical"
        android:gravity="center_vertical|center_horizontal">

        <LinearLayout
        android:layout_width="120dp"
        android:layout_height="120dp">

            <ImageView
            android:gravity="center_vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@drawable/profilepic"
            android:scaleType="fitXY"
            android:contentDescription="Main Image"
            android:clickable="true"
            android:padding="1dp"/>

    </LinearLayout>


    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/activity_vertical_margin"
        android:orientation="vertical">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:text="Large Text"
            android:id="@+id/textView"
            android:layout_gravity="center" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="   Edit Profile   "
            android:id="@+id/go_to_editprofile_btn"
            android:layout_centerVertical="true"
            android:layout_centerHorizontal="true"
            android:background="@drawable/button_bg_transparent"/>

</LinearLayout>
    </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/profile_above"
            android:background="#f7f7f7"
            android:orientation="vertical">
            <com.aldoshik.rewardtrunk.rewardtrunk5.SlidingTabLayout
                android:id="@+id/tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:elevation="2dp"/>

            <android.support.v4.view.ViewPager
                android:id="@+id/pager"
                android:layout_height="match_parent"
                android:layout_width="0dp"
                android:layout_weight="1">

            </android.support.v4.view.ViewPager>



        </LinearLayout>
    </RelativeLayout>
    <fragment
        android:id="@+id/fragment_navigation_drawer"
        android:layout_width="@dimen/nav_drawer_width"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:layout="@layout/fragment_navigation_drawer"
        android:name="com.aldoshik.rewardtrunk.rewardtrunk5.NavigationDrawerFragment"
        tools:layout="@layout/fragment_navigation_drawer" />
</android.support.v4.widget.DrawerLayout>

ViewProfile.java:

package com.company.company.testapp;

import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;


public class ViewProfile extends ActionBarActivity implements  ActionBar.TabListener {
    Toolbar toolbar;
    Context ctx = this;
    ViewPager mPager;
    SlidingTabLayout mTabs;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_profile);
        toolbar = (Toolbar)findViewById(R.id.app_bar_profile);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayShowHomeEnabled(true);
        mPager = (ViewPager) findViewById(R.id.pager);
        mPager.setAdapter(new ProfilePagerAdapter(getSupportFragmentManager()));
        mTabs = (SlidingTabLayout) findViewById(R.id.tabs);
        mTabs.setViewPager(mPager);

        NavigationDrawerFragment drawerFragment = (NavigationDrawerFragment)
                getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
        drawerFragment.setUp(R.id.fragment_navigation_drawer,(DrawerLayout)findViewById(R.id.drawer_layout),toolbar);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_view_profile, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {

    }

    @Override
    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {

    }

    @Override
    public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {

    }


    public class ProfilePagerAdapter extends FragmentPagerAdapter {

        String tabs[];
        public ProfilePagerAdapter(FragmentManager fm) {
            super(fm);
            tabs = getResources().getStringArray(R.array.tabs);
        }

        @Override
        public Fragment getItem(int position) {
            ProfileFragment profileFragment = ProfileFragment.getInstance(position);
            return profileFragment;
        }

        @Override
        public int getCount() {
            return 2;
        }

        @Override
        public CharSequence getPageTitle(int position) {
             return tabs[position];
        }
    }

    public static class ProfileFragment extends Fragment{
        public TextView textView;
        public static ProfileFragment getInstance(int position){
            ProfileFragment profileFragment = new ProfileFragment();
            Bundle args = new Bundle();
            args.putInt("Position", position);
            profileFragment.setArguments(args);
            return profileFragment;

        }

        public View OnCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState){

            View layout = inflater.inflate(R.layout.fragment_profile_self, container, false);
            textView = (TextView)  layout.findViewById (R.id.position);
            Bundle bundle = getArguments();
            if(bundle!=null){
                textView.setText(bundle.getInt("position"));
            }
            return layout;
        }
    }
}

最佳答案

问题是您在 RelativeLayout 中设置的背景

android:background="@drawable/profile_page_background_blur"

位图尺寸太大,主线程无法处理,您应该缩小位图并设置背景。

AsyncTask可以用来做到这一点:

public class ImageLoadTask extends AsyncTask<Integer, Void, Bitmap> {

    private TaskCallback callback;
    private Activity activity;

    public ImageLoadTask(Activity activity) {
        this.callback = activity;
        this.activity = activity;
    }

    @Override
    protected Bitmap doInBackground(Integer... params) {
        Bitmap bitmap;
        Display display = activity.getWindowManager().getDefaultDisplay();
        Point size = new Point();
        int width;
        int height;
        if (Build.VERSION.SDK_INT > 13) {
            display.getSize(size);
            width = size.x;
            height = size.y;
        } else {
            width = display.getWidth();
            height = display.getHeight();
        }
        return scaledDownBitmap(params[0], width, height);
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        super.onPostExecute(bitmap);
        callback.onImageLoaded(bitmap);
    }

    public interface TaskCallback {
        void onImageLoaded(Bitmap bitmap);
    }

    public Bitmap scaledDownBitmap(int resource, int reqWidth, int reqHeight) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(activity.getResource(), resource, options);

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

        options.inJustDecodeBounds = false;
        Bitmap bitmap = BitmapFactory.decodeFile(path, options);
        Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight());
        return resizedBitmap;
    }

    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;
    }
}

让您的 Activity 实现 ImageLoadTask.TaskCallback 并在那里设置 RelativeLayout 的背景。

要使用AsyncTask,请执行以下操作:

ImageLoadTask task = new ImageLoadTask(this);
task.execute(R.drawable.profile_page_background_blur)

并在任务的回调中执行以下操作:

@Override
public void onImageLoaded(Bitmap bitmap) {
    view.setBackground(new BitmapDrawable(getResouce(), bitmap));
}

我希望这有帮助。

始终记住将位图工作卸载到单独的线程中,查看 thisthis 。您还应该考虑使用 PicassoGlide或任何其他第三方库。它们简化了您的工作:)

关于java - 布局膨胀期间由 OutOfMemoryError 引起的 InflateException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32180606/

相关文章:

android - 如何使用适合所有设备的屏幕在 Webview 中显示网页的特定部分

java --list-modules 显示模块,但 jlink 找不到它

java - 如何在 unetstack 中实现水下网络的能量模型?

java - Android ArrayList 奇怪的空指针异常

android - 无法从 CursorWindow 读取第 0 行、第 1 列 (Android)

out-of-memory - Flink 死了;直接缓冲内存内存不足

java - 框架中的自定义布局

Android 4.0 设计指南

java - 如何在wave文件编辑器中面对java堆内存不足错误

android - 相机在摩托罗拉 Razr 上崩溃 - 内存不足