【问题标题】:App crashes, if I access a method in my custom view如果我在自定义视图中访问方法,应用程序崩溃
【发布时间】:2020-11-01 13:20:19
【问题描述】:

我在 Android Studio 中创建了一个自定义视图模板和一个继承自模板的自定义视图。如果我在自定义视图中访问一个方法,整个应用程序会在 Logcat 中崩溃并显示此错误消息:

2020-11-01 13:53:22.790 587-587/de.rescuemod E/AndroidRuntime: FATAL EXCEPTION: main
Process: de.rescuemod, PID: 587
java.lang.RuntimeException: Unable to start activity ComponentInfo{de.rescuemod/de.rescuemod.formulars.bike.FormBikeActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void de.rescuemod.customElements.MonoEditText.setText(java.lang.String)' on a null object reference
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2928)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3063)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1823)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:198)
    at android.app.ActivityThread.main(ActivityThread.java:6729)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:876)
 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void de.rescuemod.customElements.MonoEditText.setText(java.lang.String)' on a null object reference
    at de.rescuemod.formulars.bike.FormBikeActivity.readDatabase(FormBikeActivity.kt:653)
    at de.rescuemod.formulars.bike.FormBikeActivity.onCreate(FormBikeActivity.kt:598)
    at android.app.Activity.performCreate(Activity.java:7136)
    at android.app.Activity.performCreate(Activity.java:7127)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1272)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2908)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3063) 
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1823) 
    at android.os.Handler.dispatchMessage(Handler.java:107) 
    at android.os.Looper.loop(Looper.java:198) 
    at android.app.ActivityThread.main(ActivityThread.java:6729) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:876) 

2020-11-01 13:53:22.824 587-587/? I/Process:发送信号。 PID:587 SIG:9

这是我的父自定义视图模板:

open class CustomElementTemplate(context : Context, attrs : AttributeSet) : ConstraintLayout(context, attrs) {

/* -------------------- Member variables -------------------- */

/** Main linear layout */
val llMain = LinearLayout(context)

/** Title textview */
val txtTitle = TextView(context)

/** Getting the density of the view */
val density = context.displayMetrics.density.toInt()


/* -------------------- Initialization -------------------- */

/**
 * Primary Constructor
 */
init {

    //Constraint layout
    this.id = R.id.cl_customelementtemplate
    setPadding(8 * density, 0, 8 * density, 0)
    background = resources.getDrawable(R.drawable.border_padding, null)
    layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)



    //Title of the view
    txtTitle.id = R.id.txt_title
    val lpTitle = LayoutParams(
        LayoutParams.WRAP_CONTENT,
        LayoutParams.WRAP_CONTENT
    )

    txtTitle.setBackgroundColor(if (getDarkMode(context)) {
        resources.getColor(R.color.backgroundAccent_dark, null)
    } else {
        resources.getColor(R.color.backgroundAccent_light, null)
    })

    txtTitle.layoutParams = lpTitle
    txtTitle.setPadding(5 * density, 0, 5 * density, 0)
    txtTitle.textSize = 15f
    txtTitle.setTextColor(Color.parseColor("#8A8A8A"))
    txtTitle.visibility = View.GONE
    addView(txtTitle)



    //Main LinearLayout
    llMain.id = R.id.ll_main
    llMain.minimumHeight = 30 * density
    llMain.orientation = LinearLayout.VERTICAL
    llMain.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
    llMain.setPadding(8 * density, 20 * density, 8 * density, 14 * density)
    addView(llMain)
}


/* -------------------- Lifecycle -------------------- */

/**
 * After the layout was completly loaded in the view, execute the code here
 */
override fun onFinishInflate() {
    super.onFinishInflate()

    //Setting margins
    val constraintSet = ConstraintSet()
    constraintSet.clone(this)
    constraintSet.connect(txtTitle.id, ConstraintSet.START, this.id, ConstraintSet.START,5 * density)
    constraintSet.connect(txtTitle.id, ConstraintSet.TOP, this.id, ConstraintSet.TOP,0)
    constraintSet.applyTo(this)
}
}

自定义视图:

class MonoEditText(context: Context, attrs : AttributeSet) : CustomElementTemplate(context, attrs) {

/* -------------------- Member variables -------------------- */

/** EditText element */
private var etxt = EditText(context)



/* -------------------- Initialization -------------------- */

/**
 * Primary Constructor
 */
init {

    //Collect the values from XML
    context.theme.obtainStyledAttributes(attrs, R.styleable.MonoEditText, 0, 0).apply {

        //EditText / AutocompleteText
        if(getBoolean(R.styleable.MonoEditText_autoComplete, false)) {
            etxt = AutoCompleteTextView(context)
        }

        etxt.id = R.id.etxt_main
        etxt.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, 60 * density)
        llMain.minimumHeight = 30 * density

        llMain.addView(etxt)



        //Fill all kind of textes like titles, subtitles, etc.
        try {
            if(getString(R.styleable.MonoEditText_title)?.isNotEmpty()!!) {
                setTitle(getString(R.styleable.MonoEditText_title)!!)
            }
        } catch ( e: Exception) {}




        //InputType
        when(getString(R.styleable.MonoEditText_inputType)) {
            "0" -> etxt.inputType = InputType.TYPE_NUMBER_FLAG_SIGNED or InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
            "1" -> etxt.inputType = InputType.TYPE_CLASS_NUMBER
            "2" -> etxt.inputType = InputType.TYPE_CLASS_TEXT
            "3" -> etxt.inputType = InputType.TYPE_NUMBER_FLAG_DECIMAL
            "4" -> etxt.inputType = InputType.TYPE_TEXT_FLAG_CAP_WORDS
            "5" -> etxt.inputType = InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS
        }
        
    }
}




/* -------------------- Getter/Setter Methods -------------------- */

/**
 * Set the selected value by string
 * @param   value    String which should be choosen
 */
fun setText(value : String) {
    //etxt.setText(value)
}
}

我在 xml 活动中添加自定义视图,如下所示:

<de.rescuemod.customElements.MonoEditText
    android:id="@+id/etxt_LGEW"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:inputType="number"
    app:title="@string/LGEW" />

在活动中,我在editText字段中输入了一个值:

class FormularActivity : FormularTemplate() {

    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    //Connection to the XML-Layout-File
    setContentView(R.layout.activity_form_bike)

    ...
    etxt_LGEW.setText("Leergewicht")
    ...
}
}

感谢您的帮助

【问题讨论】:

  • 在你的最终代码 sn-p 中,etxt_LGEWnull
  • 好的,我能做些什么呢?对于我要添加“findviewbyId”并将结果存储在变量中的每个自定义视图?还是有更好的解决方案?
  • 您可以使用view bindingfindViewById() 或类似的解决方案。这与这是一个自定义视图这一事实无关。
  • 在早期版本中,我在自定义视图中使用了一个 XML,我使用“View.inflate()”将其添加到类中并且它起作用了。但是我想完全以编程方式编写它,从那时起,它就不再起作用了。而且我需要在每个活动中使用自定义视图 50-100 次,因此,我需要一种比在每个自定义视图中添加“findviewbyId”更智能的方法;)
  • 如果你不使用 CommonsWare 的建议,你总是会得到一个 NPE。

标签: android kotlin android-custom-view


【解决方案1】:

它看起来与类本身没有任何关系,而是在您的 Activity 的代码中:

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void de.rescuemod.customElements.MonoEditText.setText(java.lang.String)' on a null object reference
    at de.rescuemod.formulars.bike.FormBikeActivity.readDatabase(FormBikeActivity.kt:653)

查看此堆栈跟踪,看起来问题出在 FormBikeActivity 中的 readDatabase 函数中。它说从该函数调用 setText 会导致 NPE。我们可能需要该函数的一些代码,以及在 onCreate 中调用它的位置以及一些上下文,以查看它出错的地方。

【讨论】:

  • 是的,它是说在 FormBikeActivity 的第 653 行,您在 MonoEditText 为空的变量上调用 setText
猜你喜欢
  • 1970-01-01
  • 2017-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多