0

我正在学习使用 mvvm 进行数据绑定,但出现以下错误,我不知道主要问题是什么。

DataBinderMapperImpl.java:9: error: cannot find symbol
import gahfy.net.databinding.ActivityPostListBindingImpl;
                            ^
  symbol:   class ActivityPostListBindingImpl
  location: package gahfy.net.databinding
error: [kapt] An exception occurred: android.databinding.tool.util.LoggedErrorException: Found data binding error(s):

[databinding] {"msg":"cannot find method getLoadingVisibility() in class gahfy.net.ui.post.PostListViewModel","file":"C:\\Users\\Edgar\\Documents\\MVVMPosts\\app\\src\\main\\res\\layout\\activity_post_list.xml","pos":[{"line0":22,"col0":37,"line1":22,"col1":68}]}

error: cannot find symbol
import gahfy.net.databinding.ActivityPostListBindingImpl;
                        ^

符号:类 ActivityPostListBindingImpl 位置:包 gahfy.net.databinding

在 gahfy.net.ui.post.PostListViewModel 类中找不到方法 getLoadingVisibility()

what I have tried invalidate cache restart and rebuild and clean project it did not helped at all

在activity_post_list.xml下面

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="viewModel"
            type="gahfy.net.ui.post.PostListViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ProgressBar
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:mutableVisibility="@{viewModel.getLoadingVisibility()}" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/post_list"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:adapter="@{viewModel.getPostListAdapter()}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

在 PostListActivity.kt 下面

  import android.os.Bundle
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.LinearLayoutManager
import gahfy.net.R

import com.google.android.material.snackbar.Snackbar;
import gahfy.net.databinding.ActivityPostListBinding

class PostListActivity: AppCompatActivity() {
    private lateinit var binding: ActivityPostListBinding
    private lateinit var viewModel: PostListViewModel
    private var errorSnackbar: Snackbar? = null

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

        binding = DataBindingUtil.setContentView(this, R.layout.activity_post_list)
        binding.postList.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)

        viewModel = ViewModelProviders.of(this).get(PostListViewModel::class.java)
        viewModel.errorMessage.observe(this, Observer {
            errorMessage -> if(errorMessage != null) showError(errorMessage) else hideError()
        })
        binding.viewModel = viewModel
    }

    private fun showError(@StringRes errorMessage:Int){
        errorSnackbar = Snackbar.make(binding.root, errorMessage, Snackbar.LENGTH_INDEFINITE)
        errorSnackbar?.setAction(R.string.retry, viewModel.errorClickListener)
        errorSnackbar?.show()
    }

    private fun hideError(){
        errorSnackbar?.dismiss()
    }
}

在 PostListViewModel.kt 下面

class PostListViewModel:BaseViewModel(){
    @Inject
    lateinit var postApi: PostApi
    private val loadingVisibility: MutableLiveData<Int> = MutableLiveData()
    val errorMessage:MutableLiveData<Int> = MutableLiveData()
    val errorClickListener = View.OnClickListener { loadPosts() }
    private val postListAdapter: PostListAdapter = PostListAdapter()

    private lateinit var subscription: Disposable

    init{
        loadPosts()
    }

    private fun loadPosts(){
        subscription = postApi.getPosts()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnSubscribe { onRetrievePostListStart() }
                .doOnTerminate { onRetrievePostListFinish() }
                .subscribe(
                        // Add result
                        { result -> onRetrievePostListSuccess(result) },
                        { onRetrievePostListError() }
                )
    }

    private fun onRetrievePostListStart(){
        loadingVisibility.value = View.VISIBLE
        errorMessage.value = null
    }

    private fun onRetrievePostListFinish(){
        loadingVisibility.value = View.GONE
    }

    private fun onRetrievePostListSuccess(postList:List<Post>){
        postListAdapter.updatePostList(postList)
    }

    private fun onRetrievePostListError(){
        errorMessage.value = R.string.post_error
    }

    override fun onCleared() {
        super.onCleared()
        subscription.dispose()
    }
}

下面 BindingAdapters.kt

@BindingAdapter("mutableText")
fun setMutableText(view: TextView, text: MutableLiveData<String>?) {
    val parentActivity:AppCompatActivity? = view.getParentActivity()
    if(parentActivity != null && text != null) {
        text.observe(parentActivity, Observer { value -> view.text = value?:""})
    }


    @BindingAdapter("mutableVisibility")
    fun setMutableVisibility(view: View,  visibility: MutableLiveData<Int>?) {
        val parentActivity:AppCompatActivity? = view.getParentActivity()
        if(parentActivity != null && visibility != null) {
            visibility.observe(parentActivity, Observer { value -> view.visibility = value?:View.VISIBLE})
        }
    }

    @BindingAdapter("adapter")
    fun setAdapter(view: RecyclerView, adapter: RecyclerView.Adapter<*>) {
        view.adapter = adapter
    }


}
4

1 回答 1

0

这是关于您在 xml 中的数据绑定使用情况。1.您使用的变量必须是公共的或有公共的getter。2.如果您想使用公共变量,只需使用它的名称(无需获取)。因此,您必须在此行中进行此更改。

private val loadingVisibility: MutableLiveData<Int> = MutableLiveData()
private val postListAdapter: PostListAdapter = PostListAdapter()

val loadingVisibility: MutableLiveData<Int> = MutableLiveData()
val postListAdapter: PostListAdapter = PostListAdapter()

app:mutableVisibility="@{viewModel.getLoadingVisibility()}"
app:adapter="@{viewModel.getPostListAdapter()}"

app:mutableVisibility="@{viewModel.loadingVisibility}"
app:adapter="@{viewModel.postListAdapter}"

绑定适配器

class BindAdapters {
    companion object {
        @BindingAdapter("mutableText")
        fun setMutableText(view: TextView, text: MutableLiveData<String>?) {
            val parentActivity: AppCompatActivity? = view.getParentActivity()
            if (parentActivity != null && text != null) {
                text.observe(parentActivity, Observer { value -> view.text = value ?: "" })
            }
        }

        @BindingAdapter("mutableVisibility")
        fun setMutableVisibility(view: View, visibility: MutableLiveData<Int>?) {
            val parentActivity: AppCompatActivity? = view.getParentActivity()
            if (parentActivity != null && visibility != null) {
                visibility.observe(
                    parentActivity,
                    Observer { value -> view.visibility = value ?: View.VISIBLE })
            }
        }

        @BindingAdapter("adapter")
        fun setAdapter(view: RecyclerView, adapter: RecyclerView.Adapter<*>) {
            view.adapter = adapter
        }
    }
}

于 2020-02-28T13:30:13.280 回答