0

I am learning databinding with mvvm but I am getting following errors I did not know what is the main problem.

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;
                        ^

symbol: class ActivityPostListBindingImpl location: package gahfy.net.databinding

cannot find method getLoadingVisibility() in class gahfy.net.ui.post.PostListViewModel

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

below 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>

below 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()
    }
}

below 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()
    }
}

below 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
    }


}
Edgar
  • 860
  • 1
  • 17
  • 38

1 Answers1

0

It's about your databinding usage in xml. 1.Your used variable must be public or a have public getter. 2.If you want use public variable just use it name (without get). So you must make this changes in this lines.

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

To

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

And

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

To

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

BindAdapters

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
        }
    }
}

mahdi shahbazi
  • 1,882
  • 10
  • 19
  • after implementation your code I am getting following errors Cannot find a setter for \u003candroid.widget.ProgressBar app:mutableVisibility\u003e that accepts parameter type \u0027androidx.lifecycle.MutableLiveData\u003cjava.lang.Integer\u003e\u0027\n\nIf a binding adapter provides the setter, check that the adapter is annotated correctly and that the parameter type – Edgar Feb 28 '20 at 14:01
  • I have added BindingAdapters.kt class please check it – Edgar Feb 28 '20 at 14:09
  • @sashabeliy ```BindingAdapter``` methods must be ```static```, Is your methods static? – mahdi shahbazi Feb 28 '20 at 16:08
  • what do you mean static – Edgar Feb 28 '20 at 16:22
  • @sashabeliy look at answer, I edit it and add binding adapters in class, methods in ```companion object``` are static – mahdi shahbazi Feb 28 '20 at 16:28
  • still the same error occurs I dont know what is main problem – Edgar Feb 28 '20 at 16:35
  • still the sam error [databinding] {"msg":"Cannot find a setter for \u003candroid.widget.ProgressBar app:mutableVisibility\u003e that accepts parameter type \u0027androidx.lifecycle.MutableLiveData\u003cjava.lang.Integer\u003e\u0027\n\nIf a binding adapter provides the setter, check that the adapter is annotated correctly and that the parameter type matches.","file":"C:\\Users\\Edgar\\Documents\\MVVMPosts\\app\\src\\main\\res\\layout\\activity_post_list.xml","pos":[{"line0":22,"col0":37,"line1":22,"col1":63}]} – Edgar Feb 28 '20 at 16:41
  • what do you think main problem – Edgar Feb 28 '20 at 21:45
  • shahbizi what do you think main problem – Edgar Feb 29 '20 at 09:14
  • @sashabeliy just wait a moment I will test it and found your problem – mahdi shahbazi Feb 29 '20 at 09:50
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/208753/discussion-between-mahdi-shahbazi-and-sashabeliy). – mahdi shahbazi Feb 29 '20 at 10:08
  • I was facing same issue and after spend lots of time i found that i gave wrong package name for particular classes... I just renamed my package name "enum" to "enumsomething" and it was working – varotariya vajsi Jan 07 '22 at 16:35