测试片段:我一直在获取java.lang.RuntimeException:android.view.InflateException

问题描述 投票:0回答:1

我正在关注有关材料组件的codelab,完成后我认为我应该练习编写一些仪器测试。该应用程序正常运行。但是运行任何测试时,我总是收到此错误:

    java.lang.RuntimeException: android.view.InflateException: Binary XML file line #37: Binary 
    XML file line #37: Error inflating class 
    com.google.android.material.textfield.TextInputLayout
    at androidx.test.runner.MonitoringInstrumentation.runOnMainSync(MonitoringInstrumentation.java:450)
    at androidx.test.core.app.ActivityScenario.onActivity(ActivityScenario.java:564)
    at androidx.fragment.app.testing.FragmentScenario.internalLaunch(FragmentScenario.java:300)
    at androidx.fragment.app.testing.FragmentScenario.launchInContainer(FragmentScenario.java:282)
    at com.google.codelabs.mdc.kotlin.shrine.LoginFragmentTest.username_and_password_editTexts_visible(LoginFragmentTest.kt:64)
    at java.lang.reflect.Method.invoke(Native Method)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runners.Suite.runChild(Suite.java:128)
    at org.junit.runners.Suite.runChild(Suite.java:27)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
    at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
    at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:395)
    at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1941)
    Caused by: android.view.InflateException: Binary XML file line #37: Binary XML file line #37: Error inflating class com.google.android.material.textfield.TextInputLayout
    Caused by: android.view.InflateException: Binary XML file line #37: Error inflating class com.google.android.material.textfield.TextInputLayout
    Caused by: java.lang.reflect.InvocationTargetException
    at java.lang.reflect.Constructor.newInstance0(Native Method)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:430)
    at android.view.LayoutInflater.createView(LayoutInflater.java:645)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:787)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:727)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:858)
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:861)
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:518)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:426)
    at com.google.codelabs.mdc.kotlin.shrine.LoginFragment.onCreateView(LoginFragment.kt:19)
    at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2698)
    at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320)
    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
    at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1497)
    at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:447)
    at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2169)
    at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1992)
    at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1947)
    at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1818)
    at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:297)
    at androidx.fragment.app.testing.FragmentScenario$1.perform(FragmentScenario.java:317)
    at androidx.fragment.app.testing.FragmentScenario$1.perform(FragmentScenario.java:301)
    at androidx.test.core.app.ActivityScenario.lambda$onActivity$2$ActivityScenario(ActivityScenario.java:551)
    at androidx.test.core.app.ActivityScenario$$Lambda$4.run(Unknown Source)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428)
    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    at android.app.Instrumentation$SyncRunnable.run(Instrumentation.java:1959)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6236)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:891)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:781)
    Caused by: java.lang.IllegalArgumentException: The style on this component requires your app theme to be Theme.MaterialComponents (or a descendant).
    at com.google.android.material.internal.ThemeEnforcement.checkTheme(ThemeEnforcement.java:248)
    at com.google.android.material.internal.ThemeEnforcement.checkMaterialTheme(ThemeEnforcement.java:222)
    at com.google.android.material.internal.ThemeEnforcement.checkCompatibleTheme(ThemeEnforcement.java:150)
    at com.google.android.material.internal.ThemeEnforcement.obtainTintedStyledAttributes(ThemeEnforcement.java:120)
    at com.google.android.material.textfield.TextInputLayout.<init>(TextInputLayout.java:424)
    at com.google.android.material.textfield.TextInputLayout.<init>(TextInputLayout.java:396)
    ... 38 more

    Test running failed: Instrumentation run failed due to 'Process crashed.'

我的gradle依赖项:

dependencies {
implementation 'com.google.android.material:material:1.1.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.android.volley:volley:1.1.1'
implementation 'com.google.code.gson:gson:2.8.6'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test:core:1.2.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test:runner:1.3.0-alpha04'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha04'
debugImplementation ('androidx.fragment:fragment-testing:1.2.2'){
    exclude group: 'androidx.test', module : 'core'
}
}

我尝试更改Material依赖项的版本,但是没有运气。

我的样式文件:

<style name="AppTheme.NoActionBar" parent="Theme.MaterialComponents.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

片段布局文件:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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:background="@color/loginPageBackgroundColor"
    tools:context=".LoginFragment">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clipChildren="false"
        android:clipToPadding="false"
        android:orientation="vertical"
        android:padding="24dp"
        android:paddingTop="16dp">

        <ImageView
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="48dp"
            android:layout_marginBottom="16dp"
            app:srcCompat="@drawable/shr_logo"
            android:contentDescription="@string/shr_logo_content_description"  />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginBottom="132dp"
            android:text="@string/shr_app_name"
            android:textAllCaps="true"
            android:textSize="16sp" />

        <com.google.android.material.textfield.TextInputLayout
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:layout_margin="4dp"
            android:hint="@string/shr_hint_username"
            style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
            >
            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/username_edit_text"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                />
        </com.google.android.material.textfield.TextInputLayout>

        <com.google.android.material.textfield.TextInputLayout
            android:id="@+id/password_text_input"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="4dp"
            android:hint="@string/shr_hint_password"
            app:errorEnabled="true"
            style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
            android:inputType="textPassword"
            >
            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/password_edit_text"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </com.google.android.material.textfield.TextInputLayout>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <com.google.android.material.button.MaterialButton
                android:id="@+id/next_button"
                android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:layout_alignParentEnd="true"
                android:layout_alignParentRight="true"
                android:text = "@string/shr_button_next"
                />
            <com.google.android.material.button.MaterialButton
                android:id="@+id/cancel_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginEnd="12dp"
                android:layout_marginRight="12dp"
                android:layout_toStartOf="@id/next_button"
                android:layout_toLeftOf="@id/next_button"
                android:text="@string/shr_button_cancel"
                style="@style/Widget.MaterialComponents.Button.TextButton"
                />
        </RelativeLayout>

        <!-- Snippet from "Add buttons" section goes here. -->

    </LinearLayout>
</ScrollView>

第37行的代码是第一个TextInputLayout

片段实现:

import android.os.Bundle
import android.text.Editable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.shr_login_fragment.*
import kotlinx.android.synthetic.main.shr_login_fragment.view.*


class LoginFragment : Fragment() {

    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.shr_login_fragment, container, false)
        view.next_button.setOnClickListener {
            if(isPasswordValid(password_edit_text.text)){
                view.password_text_input.error = null
                // the false so as to not return back to the login screen again
                (activity as NavigationHost).navigateTo(ProductGridFragment(),false)
            }else{
                view.password_text_input.error = getString(R.string.shr_error_password)
            }
        }
        view.password_edit_text.setOnKeyListener { _, _, _ ->
            if(isPasswordValid(password_edit_text.text)){
                view.password_text_input.error = null
            }
            false
        }
        view.cancel_button.setOnClickListener {
            view.password_edit_text.setText("")
            view.username_edit_text.setText("")
        }
        return view
    }
    private fun isPasswordValid(text: Editable?): Boolean{
        return text!=null && text.length >= 8
    }
}
android android-fragments junit android-espresso android-instrumentation
1个回答
0
投票

将视图的所有逻辑放入onViewCreated方法内,并像这样保留onCreateView

override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
   return inflater.inflate(R.layout.shr_login_fragment, container, false)

}

然后执行onViewCreated:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
next_button.setOnClickListener {
        //your logic
    }
    password_edit_text.setOnKeyListener { _, _, _ ->
        if(isPasswordValid(password_edit_text.text)){
            view.password_text_input.error = null
        }
        false
    }
    cancel_button.setOnClickListener {
        view.password_edit_text.setText("")
        view.username_edit_text.setText("")
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.