iT邦幫忙

0

android setContentView Crash

如題,概述一下背景:
這個Bug是突然發生的,我在撰寫另外一部分的程式碼後,測試時在跳轉頁面時突然就crash了
除錯之後發現是錯在 「跳轉頁面之後 該Acticity 的setContentView(layout.xml)」

讓我很納悶的是,我修改後產生bug的程式碼跟此佈局(activity_baggage.xml)並無相關
之前在測試上時,跳轉到這個頁面也不曾crash過,所以我猜測這個bug是出在系統方面的錯誤。但我看Log並沒有很確定,爬了一下似乎是OutofMemory(OOM)但我不是很確定。因為之前沒有寫過這麼大的Android專案,加上沒碰過這樣的問題不太敢確定怎麼會突然發生這樣的問題。

另一點比較特殊的是,原本的模擬器(API_23)不行,我後來開了另外一個模擬器(API_27)來執行,跳轉到這個頁面卻完全沒有問題。

更新:
我嘗試過修改AVD的 VMHeap大小 (228->512MB)
crash的問題已經改善,可能是我這頁的Component個數太多
跳轉此Activity確實花費多了一些時間
(checkbox 一共有100多個 以Fragment方式呈現)
想請問在實務上會這樣操作嗎?還是真的要想辦法降低在該xml的元件個數?

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.v("ching","db0");
        setContentView(R.layout.activity_baggage); //Crash here
        Log.v("ching","db1");
        Initialize();
    }

activity_baggage.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".BaggageActivity">
    <include
        android:id="@+id/toolbar"
        layout="@layout/toolbar" />

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="9"></FrameLayout>

    <RelativeLayout
        android:id="@+id/funcLine"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal"
        android:elevation="10dp"
        android:background="@color/colorPrimary">

        <at.markushi.ui.CircleButton
            android:id="@+id/carried_baggage"
            android:elevation="4dp"
            android:layout_alignParentLeft="true"
            android:layout_width="64dip"
            android:layout_height="128dip"
            android:src="@drawable/baggage"
            app:cb_color="@color/material_light_orange"
            app:cb_pressedRingWidth="6dip"
            android:onClick="CarriedBaggagePage"
            />

        <at.markushi.ui.CircleButton
            android:id="@+id/life_baggage"
            android:elevation="4dp"
            android:layout_toRightOf="@id/carried_baggage"
            android:layout_width="64dip"
            android:layout_height="128dip"
            android:src="@drawable/house"
            app:cb_color="@color/material_light_orange"
            app:cb_pressedRingWidth="6dip"
            android:onClick="LifeBaggagePage"/>

        <at.markushi.ui.CircleButton
            android:id="@+id/camping_baggage"
            android:elevation="4dp"
            android:layout_toRightOf="@id/life_baggage"
            android:layout_width="64dip"
            android:layout_height="128dip"
            android:src="@drawable/camping"
            app:cb_color="@color/material_light_orange"
            app:cb_pressedRingWidth="6dip"
            android:onClick="CampingBaggagePage"/>

        <at.markushi.ui.CircleButton
            android:id="@+id/electronic_baggage"
            android:elevation="4dp"
            android:layout_toRightOf="@id/camping_baggage"
            android:layout_width="64dip"
            android:layout_height="128dip"
            android:src="@drawable/camera"
            app:cb_color="@color/material_light_orange"
            app:cb_pressedRingWidth="6dip"
            android:onClick="ElectronicBaggagePage"/>

        <at.markushi.ui.CircleButton
            android:id="@+id/selfDefined_baggage"
            android:elevation="4dp"
            android:layout_toRightOf="@id/electronic_baggage"
            android:layout_width="64dip"
            android:layout_height="128dip"
            android:src="@drawable/setting"
            app:cb_color="@color/material_light_orange"
            app:cb_pressedRingWidth="6dip"
            android:onClick="SelfDefinedBaggagePage"/>

        <at.markushi.ui.CircleButton
            android:id="@+id/btn_nextPage"
            android:elevation="4dp"
            android:layout_alignParentRight="true"
            android:layout_width="64dip"
            android:layout_height="128dip"
            android:src="@drawable/nextpage"
            app:cb_color="@color/material_light_orange"
            app:cb_pressedRingWidth="6dip"
            android:onClick="baggageSettingFinished"/>


    </RelativeLayout>
</LinearLayout>

https://imgur.com/DyQGBSn

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.tripmanager, PID: 10751
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.tripmanager/com.example.tripmanager.BaggageActivity}: android.view.InflateException: Binary XML file line #52: Binary XML file line #52: Error inflating class
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: android.view.InflateException: Binary XML file line #52: Binary XML file line #52: Error inflating class
at android.view.LayoutInflater.inflate(LayoutInflater.java:539)
at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
at android.support.v7.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:469)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140)
at com.example.tripmanager.BaggageActivity.onCreate(BaggageActivity.java:36)
at android.app.Activity.performCreate(Activity.java:6237)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
at android.app.ActivityThread.-wrap11(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:148) 
at android.app.ActivityThread.main(ActivityThread.java:5417) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
Caused by: android.view.InflateException: Binary XML file line #52: Error inflating class
at android.view.LayoutInflater.createView(LayoutInflater.java:645)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:764)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:835)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:838)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798)
at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
at android.view.LayoutInflater.inflate(LayoutInflater.java:423) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:374) 
at android.support.v7.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:469) 
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140) 
at com.example.tripmanager.BaggageActivity.onCreate(BaggageActivity.java:36) 
at android.app.Activity.performCreate(Activity.java:6237) 
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
at android.app.ActivityThread.-wrap11(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:148) 
at android.app.ActivityThread.main(ActivityThread.java:5417) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance(Native Method)
at android.view.LayoutInflater.createView(LayoutInflater.java:619)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:764) 
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704) 
at android.view.LayoutInflater.rInflate(LayoutInflater.java:835) 
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) 
at android.view.LayoutInflater.rInflate(LayoutInflater.java:838) 
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:515) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:423) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:374) 
at android.support.v7.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:469) 
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140) 
at com.example.tripmanager.BaggageActivity.onCreate(BaggageActivity.java:36) 
at android.app.Activity.performCreate(Activity.java:6237) 
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
at android.app.ActivityThread.-wrap11(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:148) 
at android.app.ActivityThread.main(ActivityThread.java:5417) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
Caused by: java.lang.OutOfMemoryError: Failed to allocate a 21344412 byte allocation with 4194304 free bytes and 15MB 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:1080)
at android.content.res.Resources.loadDrawableForCookie(Resources.java:2635)
at android.content.res.Resources.loadDrawable(Resources.java:2540)
at android.content.res.TypedArray.getDrawable(TypedArray.java:870)
at android.widget.ImageView.(ImageView.java:152)
at android.widget.ImageView.(ImageView.java:140)
at android.widget.ImageView.(ImageView.java:136)
at at.markushi.ui.CircleButton.(CircleButton.java:43)

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

0
evanchen
iT邦新手 2 級 ‧ 2020-06-23 09:45:36
最佳解答

Binary XML file line #52: Binary XML file line #52: Error inflating class
這個錯指的是 activity_baggage.xml 的第52行,
看起來是用的這個第三方元件at.markushi.ui.CircleButton
https://github.com/markushi/android-circlebutton
他的github有說已經DEPRECATED,建議改用FAB。

100個checkbox的話,除了效能,更重要的是使用體驗的問題。
對使用者來說,在同一個畫面有100個checkbox,應該是太複雜了。
如果真的需要這麼多的話,可以考慮將功能分類,開啟不同的頁面來選取checkbox。

感謝回答 我會再去看看GITHUB的部分
提到checkbox的部分我是讓使用者勾選想要的行李
是在activity_baggage利用fragment拆成四個子頁面種類
所以同時顯示在頁面倒是沒有100個這麼多
不過這邊也衍伸一個之前寫這部分的問題

在實務上,這種大量的checkbox要勾選,有沒有什麼變數方式可以來命名(給予id)這些類型相同的大量重複元件。
因為checkbox勢必要對每一個元件都進行操作
我只能開Checkbox[] m_checkbox
但每一個都還是要獨自去find他的id
例如m_checkbox[0] =findViewById(R.id.baggage_1);
難道這樣大量的元件都要每一個獨自給他一個名稱嗎?

(可能講的不是很清楚 程式碼大概是像我寫的這樣的部分)
(findId的部分好像無法以變數來當那個位置)

public void checkbox_initialize(View view){
        for (int i=0 ;i<checkbox_size ;i++){
            switch (i){
                case 0:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_1);
                    break ;
                case 1:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_2);
                    break ;
                case 2:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_3);
                    break ;
                case 3:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_4);
                    break ;
                case 4:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_5);
                    break ;
                case 5:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_6);
                    break ;
                case 6:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_7);
                    break ;
                case 7:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_8);
                    break ;
                case 8:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_9);
                    break ;
                case 9:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_10);
                    break ;
                case 10:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_11);
                    break ;
                case 11:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_12);
                    break ;
                case 12:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_13);
                    break ;
                case 13:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_14);
                    break ;
                case 14:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_15);
                    break ;
                case 15:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_16);
                    break ;
                case 16:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_17);
                    break ;
                case 17:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_18);
                    break ;
                case 18:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_19);
                    break ;
                case 19:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_20);
                    break ;
                case 20:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_21);
                    break ;
                case 21:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_22);
                    break ;
                case 22:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_23);
                    break ;
                case 23:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_24);
                    break ;
                case 24:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_25);
                    break ;
                case 25:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_26);
                    break ;
                case 26:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_27);
                    break ;
                case 27:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_28);
                    break ;
                case 28:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_29);
                    break ;
                case 29:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_30);
                    break ;
                case 30:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_31);
                    break ;
                case 31:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_32);
                    break ;
                case 32:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_33);
                    break ;
                case 33:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_34);
                    break ;
                case 34:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_35);
                    break ;
                case 35:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_36);
                    break ;
                case 36:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_37);
                    break ;
                case 37:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_38);
                    break ;
                case 38:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_39);
                    break ;
                case 39:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_40);
                    break ;
                case 40:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_41);
                    break ;
                case 41:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_42);
                    break ;
                case 42:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_43);
                    break ;
                case 43:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_44);
                    break ;
                case 44:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_45);
                    break ;
                case 45:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_46);
                    break ;
                case 46:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_47);
                    break ;
                case 47:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_48);
                    break ;
                case 48:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_49);
                    break ;
                case 49:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_50);
                    break ;
                case 50:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_51);
                    break ;
                case 51:
                    camping_checkbox_array[i]= view.findViewById(R.id.checkbox_camping_52);
                    break ;
            }
        }
    }

資料來源

Checkbox[] m_checkbox;
for(int i=0; i<m_checkbox.length; i++) {
{
   String chkID = "checkbox_camping_" + (i+1);

   int resID = getResources().getIdentifier(chkID, "id", getPackageName());
   m_checkbox[i] = ((Checkbox) findViewById(resID));
   m_checkbox[i].setOnClickListener(this);
}

原來如此可以這樣使用 感謝
我一直以來這種大量都是這樣命名
原來我一直在用笨方法 謝謝

我要發表回答

立即登入回答