首页 > 解决方案 > 如何使用数据绑定正确地进行事件处理

问题描述

如上所述,我试图使用数据绑定(准确地说是方法引用)对几个按钮进行有效的事件处理,但似乎不能让它工作。看起来 onCLick 侦听器找不到引用的方法。不知道为什么会这样。以下是相关的代码片段和我不断收到的错误:

主要活动:

class MainActivity : AppCompatActivity(), EntryScreenFragment.FragInterface, ImageChoiceFragment.FragInterface,
        AccelerometerDisplayFragment.FragInterface, JSONPostChooserFragment.FragInterface {
    companion object {
        const val MY_REQUEST_CODE_1 = 24215
        const val MY_REQUEST_CODE_2 = 31345
    }

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    setSupportActionBar(findViewById(R.id.my_toolbar))

    val fragment = EntryScreenFragment()
    fragment.listener = this

    addNewFragment(fragment)

    supportActionBar?.setHomeAsUpIndicator(R.mipmap.ic_launcher_round)
    supportActionBar?.setHomeButtonEnabled(true)
    supportActionBar?.setDisplayHomeAsUpEnabled(true)
}

override fun screenshotAccelerometer(): Boolean {
    if (isExternalStorageWritable()) checkAndAskForPermissionToWrite()
    return true
}

override fun imageChoiceButtonclick1(input: String) {
    val fragment = ImageDisplayFragment.newInstanceWithText(getString(R.string.url_1), input)
    addNewFragment(fragment)
}

override fun imageChoiceButtonclick2(input: String) {
    val fragment = ImageDisplayFragment.newInstanceWithText(getString(R.string.url_2), input)
    addNewFragment(fragment)
}

override fun imageChoiceButtonclick3(input: String) {
    val fragment = ImageDisplayFragment.newInstanceWithText(getString(R.string.url_3), input)
    addNewFragment(fragment)
}

override fun entryScreenButtonClickImages() {
    val fragment = ImageChoiceFragment()
    fragment.listener = this
    addNewFragment(fragment)
}

override fun entryScreenButtonClickAccelerometer() {
    val fragment = AccelerometerDisplayFragment()
    fragment.listener = this
    addNewFragment(fragment)
}

override fun entryScreenButtonClickJSON() {
    //   val fragment=JSONLoaderFragment()
    val fragment = JSONPostChooserFragment()
    fragment.listener = this
    addNewFragment(fragment)
}

override fun entryScreenButtonClickNoXML() {
    val fragment = NoXMLFragment()
    addNewFragment(fragment)
}

override fun entryScreenButtonClickCheckForInternet() {
    return checkAndAskForPemissionToAccessNetworkState()
}

override fun entryScreenButtonClickImageBind() {
    val fragment =ImageBindFragment()
    addNewFragment(fragment)
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    menuInflater.inflate(R.menu.test_menu, menu)
    return true
}

override fun onOptionsItemSelected(item: MenuItem?): Boolean {
    when (item?.itemId) {
        android.R.id.home -> {
            val mgr = supportFragmentManager
            if (!mgr.popBackStackImmediate())
                finish()

        }
        R.id.action_settings -> {

        }
        else -> {

        }
    }
    return super.onOptionsItemSelected(item)
}

override fun createChosenPostFragment(data: PostEntity) {
    val fragment = ChosenJSONPostFragment.newInstance(data)
    addNewFragment(fragment)

}

override fun onStart() {
    super.onStart()
}

override fun onResume() {
    super.onResume()
}

override fun onPause() {
    super.onPause()
}

fun addNewFragment(f: Fragment) {
    val transaction = supportFragmentManager.beginTransaction()
    transaction.setCustomAnimations(R.anim.anim_entry_1, R.anim.anim_exit_1, R.anim.anim_entry_1, R.anim.anim_exit_1)
    transaction.add(R.id.fragment_container, f).addToBackStack(UUID.randomUUID().toString()) //potential error
    transaction.commit()
}

private fun checkAndAskForPermissionToWrite() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {

        ActivityCompat.requestPermissions(this,
                arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), MY_REQUEST_CODE_1)
    } else {
        if (isExternalStorageWritable())
            return

    }
}

private fun checkAndAskForPemissionToAccessNetworkState() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_NETWORK_STATE)
            != PackageManager.PERMISSION_GRANTED) {

        ActivityCompat.requestPermissions(this,
                arrayOf(Manifest.permission.ACCESS_NETWORK_STATE), MY_REQUEST_CODE_2)
    } else {
        //what to do with permission
        openWifi()
    }
    return
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
    when (requestCode) {
        MY_REQUEST_CODE_1 -> {
            if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                //what to do with permission
                if (isExternalStorageWritable())
                    return
            }
        }

        MY_REQUEST_CODE_2 -> {
            if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                openWifi()
            }
        }
        else -> {
            //...
            Toast.makeText(this, "Permission not granted", Toast.LENGTH_LONG).show()
        }
    }
}

fun openWifi() {
    if (isNetworkAvailable())
    else {
        val bar = Snackbar.make(findViewById(R.id.EntryScreenCoordinatorLayout), getString(R.string.internet_check_snackbar_text), Snackbar.LENGTH_LONG)
        bar.show()
        bar.setAction(getString(R.string.internet_check_snackbar_action)) { startActivity(Intent(Settings.ACTION_WIFI_SETTINGS)) }
    }
}

private fun isNetworkAvailable(): Boolean {
    val cm = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val activeNetwork: NetworkInfo? = cm.activeNetworkInfo
    return activeNetwork?.isConnectedOrConnecting == true
}

fun isExternalStorageWritable(): Boolean {
    return Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED
}

片段:

class EntryScreenFragment : Fragment() {
    interface FragInterface {
        fun entryScreenButtonClickImages()
        fun entryScreenButtonClickAccelerometer()
        fun entryScreenButtonClickJSON()
        fun entryScreenButtonClickNoXML()
        fun entryScreenButtonClickCheckForInternet()
        fun entryScreenButtonClickImageBind()
    }

var listener: FragInterface? = null
lateinit var binding: FragmentEntryScreenBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    binding=DataBindingUtil.inflate(inflater,R.layout.fragment_entry_screen,container,false)
    binding.handlers= EntryScreenEventHandlers()
    binding.handlers.listener=listener
    binding.root.isClickable=true
    return binding.root


}

片段的 XML:

<layout>

<data>

    <variable
        name="handlers"
        type="com.example.robert.testapp.EntryScreenEventHandlers" />
</data>

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/EntryScreenCoordinatorLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorWhite"
    android:orientation="vertical">

    <Button
        android:id="@+id/EntryScreenButtonToImages"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|start"
        android:onClick="@{handlers::entryScreenButtonClickImages}"
        android:text="Make Fragment"
        app:layout_behavior="com.example.robert.testapp.ButtonSnackbarBehaviour" />

    <Button
        android:id="@+id/EntryScreenAccelerometerButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:onClick="@{handlers::entryScreenButtonClickAccelerometer}"
        android:text="Accelerometer screen"
        app:layout_behavior="com.example.robert.testapp.ButtonSnackbarBehaviour" />

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <Button
            android:id="@+id/EntryScreenButtonToJSONLoader"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{handlers::entryScreenButtonClickJSON}"
            android:text="@string/entry_screen_load_json_button"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toRightOf="@id/EntryScreenButtonToNoXmlFragment"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/EntryScreenButtonToNoXmlFragment"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{handlers::entryScreenButtonClickNoXML"
            android:text="@string/entry_screen_to_no_xml_button"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toLeftOf="@id/EntryScreenButtonToJSONLoader"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/EntryScreenButtonInternetCheck"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{handlers::entryScreenButtonClickCheckForInternet"
            android:text="@string/entry_screen_internet_check_button"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/EntryScreenButtonImageBind"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{handlers::entryScreenButtonClickImageBind"
            android:text="@string/entry_screen_image_bind_button"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </android.support.constraint.ConstraintLayout>

</android.support.design.widget.CoordinatorLayout>

事件处理类:

class EntryScreenEventHandlers {
    var listener : EntryScreenFragment.FragInterface? = null
    fun entryScreenButtonClickImages(){listener?.entryScreenButtonClickImageBind()}
    fun entryScreenButtonClickAccelerometer(){listener?.entryScreenButtonClickAccelerometer()}
    fun entryScreenButtonClickJSON(){listener?.entryScreenButtonClickJSON()}
    fun entryScreenButtonClickNoXML(){listener?.entryScreenButtonClickNoXML()}
    fun entryScreenButtonClickCheckForInternet(){listener?.entryScreenButtonClickCheckForInternet()}
    fun entryScreenButtonClickImageBind() {listener?.entryScreenButtonClickImageBind()}

}

最后,错误消息:

[kapt] An exception occurred: android.databinding.tool.util.LoggedErrorException: Found data binding errors.
****/ data binding error ****msg:Listener class android.view.View.OnClickListener with method onClick did not match signature of any method handlers::entryScreenButtonClickImages
file:C:\Users\Robert\Desktop\AP_projects\app\src\main\res\layout\fragment_entry_screen.xml
loc:22:31 - 22:68
****\ data binding error ****

at android.databinding.tool.processing.Scope.assertNoError(Scope.java:112)
at android.databinding.annotationprocessor.ProcessDataBinding.doProcess(ProcessDataBinding.java:101)
at android.databinding.annotationprocessor.ProcessDataBinding.process(ProcessDataBinding.java:65)
at org.jetbrains.kotlin.kapt3.ProcessorWrapper.process(annotationProcessing.kt:133)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$200(JavacProcessingEnvironment.java:91)
at com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.runContributingProcs(JavacProcessingEnvironment.java:627)
at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1033)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1198)
at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170)
at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1068)
at org.jetbrains.kotlin.kapt3.AnnotationProcessingKt.doAnnotationProcessing(annotationProcessing.kt:89)
at org.jetbrains.kotlin.kapt3.AnnotationProcessingKt.doAnnotationProcessing$default(annotationProcessing.kt:46)
at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.runAnnotationProcessing(Kapt3Extension.kt:226)
at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:181)
at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:93)
at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM$analyzeFilesWithJavaIntegration$2.invoke(TopDownAnalyzerFacadeForJVM.kt:97)
at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:107)
at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:84)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:374)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:64)
at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:101)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:365)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:130)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:161)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:63)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:108)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:52)
at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:92)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$1$1$2.invoke(CompileServiceImpl.kt:395)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$1$1$2.invoke(CompileServiceImpl.kt:97)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:909)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:97)
at org.jetbrains.kotlin.daemon.common.DummyProfiler.withMeasure(PerfUtils.kt:137)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.checkedCompile(CompileServiceImpl.kt:939)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.doCompile(CompileServiceImpl.kt:908)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:394)
at sun.reflect.GeneratedMethodAccessor105.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:346)
at sun.rmi.transport.Transport$1.run(Transport.java:200)
at sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)    

标签: androidkotlinevent-handlingandroid-databinding

解决方案


推荐阅读