Android Orientation更改导致应用程序崩溃

时间:2014-05-15 11:31:57

标签: java android

这只发生过一次,但我有点担心。我正在测试应用程序更改方向和应用程序崩溃。从来没有发生过,所以只是想看看是否有其他人有这个问题以及我能做些什么来解决它。请参阅下面的日志:

05-15 12:13:07.304: E/AndroidRuntime(2596): FATAL EXCEPTION: main
05-15 12:13:07.304: E/AndroidRuntime(2596): java.lang.RuntimeException: Unable to start activity      ComponentInfo{com./.hearing.InstructionsActivity}:     android.view.InflateException: Binary XML file line #8: Error inflating class <unknown>
05-15 12:13:07.304: E/AndroidRuntime(2596):     at   android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3740)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.app.ActivityThread.access$700(ActivityThread.java:141)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1262)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.os.Handler.dispatchMessage(Handler.java:99)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.os.Looper.loop(Looper.java:137)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.app.ActivityThread.main(ActivityThread.java:5103)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at java.lang.reflect.Method.invokeNative(Native Method)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at java.lang.reflect.Method.invoke(Method.java:525)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at dalvik.system.NativeStart.main(Native Method)
05-15 12:13:07.304: E/AndroidRuntime(2596): Caused by: android.view.InflateException: Binary XML file line #8: Error inflating class <unknown>
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.view.LayoutInflater.createView(LayoutInflater.java:620)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.view.LayoutInflater.onCreateView(LayoutInflater.java:669)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:694)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.view.LayoutInflater.rInflate(LayoutInflater.java:755)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.view.LayoutInflater.inflate(LayoutInflater.java:353)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:267)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at com.actionbarsherlock.internal.ActionBarSherlockNative.setContentView(ActionBarSherlockNative.java:133)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at   com.actionbarsherlock.app.SherlockActivity.setContentView(SherlockActivity.java:229)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at .InstructionsActivity.onCreate(InstructionsActivity.java:40)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.app.Activity.performCreate(Activity.java:5133)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175)
05-15 12:13:07.304: E/AndroidRuntime(2596):     ... 12 more
05-15 12:13:07.304: E/AndroidRuntime(2596): Caused by: java.lang.reflect.InvocationTargetException
05-15 12:13:07.304: E/AndroidRuntime(2596):     at java.lang.reflect.Constructor.constructNative(Native Method)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.view.LayoutInflater.createView(LayoutInflater.java:594)
05-15 12:13:07.304: E/AndroidRuntime(2596):     ... 26 more
05-15 12:13:07.304: E/AndroidRuntime(2596): Caused by: java.lang.OutOfMemoryError
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:503)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:356)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:800)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.content.res.Resources.loadDrawable(Resources.java:2105)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.widget.ImageView.<init>  (ImageView.java:127)
05-15 12:13:07.304: E/AndroidRuntime(2596):     at android.widget.ImageView.<init>(ImageView.java:117)
05-15 12:13:07.304: E/AndroidRuntime(2596):     ... 29 more

所以对我而言看起来它有一个膨胀布局的问题。我不知道是怎么回事,因为在坠毁之前我已经改变了4次方向。

进一步向下有一个java.lang.OutOfMemoryError错误,所以我认为这导致了android.view.InflateException

非常感谢任何帮助。感谢

修改

这是它崩溃的活动:

public class InstructionsActivity extends MenuActivity {
private ScrollView mScrollButton;
private WebView topContent;
private WebView bottomContent;
private boolean mMoreInfoTop = false;
private int mYdelta = 0;
private int mBottomOffset = 0;
private ActivityHelper activityHelper;
private boolean isPhone;
private String topHtml;
private String bottomHtml;
private String flag;

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.instructions);

    activityHelper = new ActivityHelper(this);
    activityHelper.getScreenTag(R.id.instructions);
    activityHelper.getDrawableFolder();
    activityHelper.setTitleTextSize(R.string.Hearing_Test, true);
    isPhone = activityHelper.isPhone();

    if(isPhone){
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }

    mScrollButton = (ScrollView) findViewById(R.id.scroll_view);
    flag = String.valueOf(getIntent().getStringExtra("Flag"));

    if (flag.equalsIgnoreCase("firstInstructions")) {
        topHtml = this.getString(R.string.top_content);

        Button startTest = (Button) findViewById(R.id.test);
        startTest.setText(R.string.start_test);
    }else if(flag.equalsIgnoreCase("secondInstructions")){
        topHtml = this.getString(R.string.switch_file);

        Button startTest = (Button) findViewById(R.id.test);
        startTest.setText(R.string.continue_test);
    }

    bottomHtml = this.getString(R.string.bottom_content);
    topContent = (WebView) findViewById(R.id.top_content);
    topContent.setBackgroundColor(0);
    bottomContent = (WebView) findViewById(R.id.bottom_content);
    bottomContent.setBackgroundColor(0);
    bottomContent.getSettings().setUseWideViewPort(false);

    topContent.loadUrl("file:///android_asset/html/" + topHtml);
    bottomContent.loadUrl("file:///android_asset/html/" + bottomHtml);

    getMargins();

    setResult(RESULT_OK);
}

public void getMargins() {

    ViewTreeObserver viewTreeObserver = topContent.getViewTreeObserver();

    viewTreeObserver.addOnPreDrawListener(new OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            int topHeight = topContent.getMeasuredHeight();
            int bottomHeight = bottomContent.getMeasuredHeight();

            if (isPhone) {
                if (topHeight != 0) {
                    Log.d("Web View Height", "Continue Height: "
                            + topHeight);
                    if (mScrollButton != null) {
                        RelativeLayout instructions = (RelativeLayout) findViewById(R.id.more_info);
                        instructions.post(mAddMargin);
                        topContent.getViewTreeObserver()
                                .removeOnPreDrawListener(this);
                    }
                    topContent.getViewTreeObserver()
                            .removeOnPreDrawListener(this);
                }
            } else if (!isPhone) {
                if (topHeight != 0 && bottomHeight != 0) {
                    Log.d("Web View Height", "top Height: " + topHeight
                            + "bottom height:" + bottomHeight);
                    RelativeLayout instructions = (RelativeLayout) findViewById(R.id.more_info);
                    instructions.post(mAddMargin);
                    topContent.getViewTreeObserver()
                            .removeOnPreDrawListener(this);
                }
            }
            return false;
        }
    });
}

Runnable mAddMargin = new Runnable() {
    @Override
    public void run() {
        try {
            int marginHeight;

            if (isPhone) {
                marginHeight = activityHelper.getMarginHeight(R.id.more_info, R.id.bottom_content);
                RelativeLayout buttonHolder = (RelativeLayout) findViewById(R.id.instructionsLayout);
                mBottomOffset = buttonHolder.getBottom();
                mScrollButton = (ScrollView) findViewById(R.id.scroll_view);
                mYdelta = mScrollButton.getScrollY();
                activityHelper.setMarginHeight(marginHeight, R.id.instructionsLayout);
            } else if (!isPhone) {
 //                 int sideMargin = activityHelper.getWebViewMargin(R.id.bottom_content);
//                  if(sideMargin != 0){
//                      activityHelper.setWebViewMargin(sideMargin, R.id.top_content);
//                      activityHelper.setWebViewMargin(sideMargin, R.id.bottom_content);
//                  }
                marginHeight = activityHelper.getMarginHeight(R.id.more_info, R.id.bottom_content);
                activityHelper.setMarginHeight(marginHeight, R.id.more_info);
            }
        } catch (Exception e) {
            Log.e("Scroll View", "Couldn't run mAddMargin:", e);
        }
    }
};

public void onClickHandler(View aView) {

    if (flag.equalsIgnoreCase("firstInstructions")) {
        Intent intent = new Intent(this, HearingTestActivity.class);
        startActivity(intent);
    }else if(flag.equalsIgnoreCase("secondInstructions")){
        finish();
    }
}

public void infoView(View aView) {
    Intent intent = new Intent(this, InfoActivity.class);
    startActivity(intent);
}

public void onMoreInstructions(View aView) {
    // Scroll the start button to the top of the screen.
    mScrollButton.post(new Runnable() {

        @Override
        public void run() {
            if (mMoreInfoTop) {
                mMoreInfoTop = false;
                mScrollButton.scrollTo(0, mYdelta);
            } else {
                mMoreInfoTop = true;
                mScrollButton.scrollTo(0, mBottomOffset);
            }
        }
    });
}
}

你还需要我的其他代码吗?

新代码:

这是我更新的代码:

public void getMargins() {

    ViewTreeObserver viewTreeObserver = topContent.getViewTreeObserver();

    x = new OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            int topHeight = topContent.getMeasuredHeight();
            int bottomHeight = bottomContent.getMeasuredHeight();

            if (isPhone) {
                if (topHeight != 0) {
                    Log.d("Web View Height", "Continue Height: "
                            + topHeight);
                    if (mScrollButton != null) {
                        RelativeLayout instructions = (RelativeLayout) findViewById(R.id.more_info);
                        instructions.post(mAddMargin);
                        topContent.getViewTreeObserver()
                                .removeOnPreDrawListener(this);
                    }
                    topContent.getViewTreeObserver()
                            .removeOnPreDrawListener(this);
                }
            } else if (!isPhone) {
                if (topHeight != 0 && bottomHeight != 0) {
                    Log.d("Web View Height", "top Height: " + topHeight
                            + "bottom height:" + bottomHeight);
                    RelativeLayout instructions = (RelativeLayout) findViewById(R.id.more_info);
                    instructions.post(mAddMargin);
                    topContent.getViewTreeObserver()
                            .removeOnPreDrawListener(this);
                }
            }
            return false;
        } 
    };

    viewTreeObserver.addOnPreDrawListener(x);
}

现在我将监听器保存到变量x

onDestroy方法:

@Override
protected void onDestroy() {
    super.onDestroy();
    if(x != null){
        topContent.getViewTreeObserver()
            .removeOnPreDrawListener(x);
    }
}

然后检查变量x是否为null,如果它是删除监听器?

我对此是否正确?感谢

2 个答案:

答案 0 :(得分:1)

这看起来像是经典的内存泄漏情况。

最有可能的是,您在监听器或Activity中保留对某个UI组件(或者甚至是AsyncTask)的实时引用,导致Activity实例泄露(保持不被垃圾收集)当你转动设备时 - 因为方向改变,另一个Activity实例被创建,旧的实例应该被销毁和收集。

将设备翻转3次后,您将拥有4份副本 - 因此是OOM。

另一种可能性是,当您的Bitmap被销毁时,您手动解码recycle()而不是在其上调用Activity

是的,就像那些人在评论中所说的那样,在你发布你的代码之前,没有什么比这更具体了。

UPD 哦,是的,既然代码在那里,很可能是你的问题的根源在匿名类中的某个地方(OnPreDrawListenerRunnable) 。首先,并非所有条件都能保证您的侦听器被删除 - 我不确定这究竟是导致泄漏的原因,但是请考虑检查侦听器是否仍然存在并在onDestroy()中删除它。但更普遍的想法是,任何不重要的匿名和嵌套非静态类都是一个坏主意,因为它们存储对包含类的实例的隐式引用 - 在本例中为Activity。如果任何代码发生任何未预料到的事情 - 它可能导致包含实例被保留。

因此,最安全的策略是避免使用非静态嵌套(更简单的匿名)类,除非它们携带的逻辑非常简单,以至于您完全确定其含义。

我的首选方法是创建静态嵌套Listener(或AsyncTask s,Runnable等),通过WeakReference引用他们需要的所有内容。最明显的解决方案是将Activity的引用存储在成员WeakReference<InstructionsActivity>中,并在执行相应的代码时检查null。如果它返回null - 这意味着您的Activity被销毁,只需立即return

<强> UPD 另外,考虑使用Eclipse MAT(here's a good article,谷歌更多)来检测内存泄漏。它具有在HPROF转储文件上运行OQL查询的强大功能,这样您就可以查询可疑泄漏类(活动类),如果有两个或更多个 - 您知道自己遇到了问题。它甚至会向您显示保留它们的对象 - 查找 GC根的路径

答案 1 :(得分:0)

这可能是配置更改的原因,在活动内的mainifest文件中添加以下属性。您可以根据您的要求进行更改

android:configChanges="orientation|screenSize|keyboard|screenLayout"