创建依赖于初始化单例的视图时崩溃

时间:2017-07-03 18:13:38

标签: android android-custom-view android-lifecycle

我维护了一个导致崩溃的库,让我感到困惑。

该库为用户提供了扩展View的自定义FrameLayout。此自定义View在其构造函数中访问单例(也由库定义):

CustomView(Context context, AttributeSet attributeSet, int defStyleAttr) {
    super(context, attributeSet, defStyleAttr);

    // Other initialization.

    mySingleton = MySingleton.getSharedInstance();
}

// Two-parameter and one-parameter constructors delegate to the three-parameter constructor above.

如果先前未调用配置方法MySingleton::getSharedInstance,则方法MySingleton::initSharedInstance会抛出异常:

private static void initSharedInstance(Application application) {
    synchronized (MySingleton.class) {
        if (sharedInstance == null) {
            sharedInstance = new MySingleton(application);
        }
    }
}

public static MySingleton getSharedInstance() {
    synchronized (MySingleton.class) {
        if (sharedInstance == null) {
            throw new IllegalStateException("You must call initSharedInstance before calling getSharedInstance.");
        }
    }

    return sharedInstance;
}

我指示图书馆用户使用MySingleton::initSharedInstance方法拨打Application::onCreate,并向报告此次崩溃的用户确认他们正在这样做。

这是一个示例堆栈跟踪:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example/com.example.activity.ManageCamerasActivity}: android.view.InflateException: Binary XML file line #11: Binary XML file line #1: Error inflating class com.github.stkent.amplify.prompt.DefaultLayoutPromptView
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3319)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3415)
    at android.app.ActivityThread.access$1100(ActivityThread.java:229)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1821)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:7325)
    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)
Caused by: android.view.InflateException: Binary XML file line #11: Binary XML file line #1: Error inflating class com.github.stkent.amplify.prompt.DefaultLayoutPromptView
    at android.view.LayoutInflater.inflate(LayoutInflater.java:551)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:429)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:380)
    at android.support.v7.app.m.b(SourceFile:288)
    at android.support.v7.app.e.setContentView(SourceFile:140)
    at com.example.activity.ManageCamerasActivity.onCreate(SourceFile:232)
    at android.app.Activity.performCreate(Activity.java:6904)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1136)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3266)
    ... 9 more
Caused by: android.view.InflateException: Binary XML file line #1: Error inflating class com.github.stkent.amplify.prompt.DefaultLayoutPromptView
    at android.view.LayoutInflater.createView(LayoutInflater.java:657)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:776)
    at android.view.LayoutInflater.parseInclude(LayoutInflater.java:966)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:843)
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:527)
    ... 17 more
Caused by: java.lang.reflect.InvocationTargetException
    at java.lang.reflect.Constructor.newInstance(Native Method)
    at android.view.LayoutInflater.createView(LayoutInflater.java:631)
    ... 22 more
Caused by: java.lang.IllegalStateException: You must call initSharedInstance before calling getSharedInstance.
    at com.github.stkent.amplify.b.a.b(SourceFile:101)
    at com.github.stkent.amplify.prompt.a.<init>(SourceFile:113)
    at com.github.stkent.amplify.prompt.DefaultLayoutPromptView.<init>(SourceFile:52)
    at com.github.stkent.amplify.prompt.DefaultLayoutPromptView.<init>(SourceFile:44)
    ... 24 more

显然,MySingleton::getSharedInstance之前正在调用MySingleton::initSharedInstance,即CustomView之前正在调用Application::onCreate构造函数,但我不知道具体情况如何。我认为在执行任何Application / Activity / Fragment代码之前,View实例始终是完全创建的。

这里发生了什么?

N.B。:如果链接到更具体的实施细节会有用,请对此作出评论。

1 个答案:

答案 0 :(得分:-1)

在getSharedInstance(Application a)中执行:if(instance == null){ initSharedInstance(a); }