1

I am trying to make an android application that displays a list of coupons to the user to choose from using RecyclerView. I am trying to use DataBinding to bind the details of the coupons to a coupon XML template, and then those coupons to the RecyclerView.

when I try to build, I keep on getting error:

cannot find symbol class CouponItemBindingImpl

Here is my XML code for the Coupon Item template:

<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">


<android.support.v7.widget.CardView
    android:id="@+id/card"
    android:layout_width="match_parent"
    android:layout_height="120dp"
    app:cardBackgroundColor="@android:color/transparent"
    app:cardCornerRadius="14dp"
    app:cardElevation="6dp">


    <LinearLayout
        android:id="@+id/linearLayoutHorizontal"
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:orientation="horizontal"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <data xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            class="CouponItem">
            <import type="com.example.mmcke.campuscoupons.model.Coupon"/>

            <variable
                name="data"
                type="Coupon" />
            <import type="com.example.mmcke.campuscoupons.R"/>
        </data>

        <LinearLayout
            android:id="@+id/linearLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:orientation="vertical">

            <TextView
                android:id="@+id/name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@{data.name}"
                android:textSize="24sp" />

            <TextView
                android:id="@+id/details"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@{data.details}"
                android:textSize="14sp" />

        </LinearLayout>
    </LinearLayout>
</android.support.v7.widget.CardView>
</layout>

Here is the XML code for my main activity, the screen containing the RecyclerView:

<?xml version="1.0" encoding="utf-8"?>

<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto">

<data>
    <import type="com.example.mmcke.campuscoupons.model.Coupon"/>
    <variable
        name="data"
        type="Coupon"/>

</data>

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.mmcke.campuscoupons.controllers.MainActivity">

    <TextView
        android:id="@+id/header"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="Campus Coupons"
        android:textSize="24sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="368dp"
        android:layout_height="455dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/header"
        app:layoutManager="android.support.v7.widget.LinearLayoutManager">
    </android.support.v7.widget.RecyclerView>

</android.support.constraint.ConstraintLayout>

</layout>

Here is the java code for my Main Activity:

package com.example.mmcke.campuscoupons.controllers;

import android.content.Context;
import android.databinding.BindingAdapter;
import android.databinding.DataBindingUtil;
import android.databinding.ViewDataBinding;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;

import com.example.mmcke.campuscoupons.BR;
import com.example.mmcke.campuscoupons.R;
import com.example.mmcke.campuscoupons.databinding.ActivityMainBinding;
import com.example.mmcke.campuscoupons.model.Coupon;
import com.example.mmcke.campuscoupons.model.CouponAdapter;
import com.example.mmcke.campuscoupons.model.Model;
import com.example.mmcke.campuscoupons.model.School;
import com.example.mmcke.campuscoupons.databinding.CouponItemBinding;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

private final Model model = Model.getInstance();
private ArrayList<Coupon> coupons = new ArrayList<Coupon>();
private ActivityMainBinding binding;
private RecyclerView recyclerView;
private CouponAdapter adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

    coupons = getEnumFromString(School.class, model.getCurrentUser().getSchoolName()).getCoupons();
    recyclerView = (RecyclerView)findViewById(R.id.recyclerView);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));

    adapter = new CouponAdapter(this, coupons);
    recyclerView.setAdapter(adapter);

}

@BindingAdapter({"entries", "layout"})
public static <Coupon> void setEntries(ViewGroup viewGroup, ArrayList<Coupon> entries, int layoutID) {
    if (entries != null) {
        LayoutInflater inflater = (LayoutInflater)viewGroup.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        for (int i = 0; i < entries.size(); i++) {
            Coupon entry = entries.get(i);
            ViewDataBinding binding = DataBindingUtil.inflate(inflater, layoutID, viewGroup, true);
            //binding.setVariable(BR.data, entry);
        }
    }
}

public static <School extends Enum<School>> School getEnumFromString (Class<School> c, String string) {
    if (c != null && string != null) {
        try {
            return Enum.valueOf(c, string.trim().toUpperCase());
        } catch (IllegalArgumentException ex) {

        }
    }
    return null;
}
}

Here is the holder I made for my Coupon Item:

package com.example.mmcke.campuscoupons.model;

import android.content.ClipData;
import android.databinding.ViewDataBinding;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.mmcke.campuscoupons.BR;
import com.example.mmcke.campuscoupons.R;
import com.example.mmcke.campuscoupons.databinding.ActivityMainBinding;
import com.example.mmcke.campuscoupons.databinding.CouponItemBinding;


/**
 *
 * A class to help with displaying coupons
 * Created by mmcke on 11/21/2018.
 */

public class CouponHolder extends RecyclerView.ViewHolder {

final ViewDataBinding binding;
//private final CouponItemBinding binding;

public CouponHolder(CouponItemBinding binding) {
    super(binding.getRoot());
    this.binding = binding;
}

public void bind(Object obj) {
    binding.setVariable(BR.data, obj);
    binding.executePendingBindings();
}
}

And finally, here is the adapter I made for my Coupon Item:

package com.example.mmcke.campuscoupons.model;

import android.content.Context;
import android.databinding.DataBindingUtil;
import android.databinding.ViewDataBinding;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.example.mmcke.campuscoupons.BR;
import com.example.mmcke.campuscoupons.R;
import com.example.mmcke.campuscoupons.databinding.ActivityMainBinding;
import com.example.mmcke.campuscoupons.databinding.CouponItemBinding;

import java.util.ArrayList;

/**
 *
 * A class to help with displaying coupons
 * Created by mmcke on 11/21/2018.
 */

public class CouponAdapter extends RecyclerView.Adapter<CouponHolder>{

private Context context;
private ArrayList<Coupon> coupons;

public CouponAdapter(Context _context, ArrayList<Coupon> _coupons) {
    this.context = _context;
    this.coupons = _coupons;
}

@Override
public int getItemCount() {
    return coupons.size();
}

@Override
public CouponHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
    CouponItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.coupon_item, parent, false);
    return new CouponHolder(binding);
}

@Override
public void onBindViewHolder(CouponHolder holder, int position) {
    Coupon data = coupons.get(position);
    holder.binding.setVariable(BR.data, data);
}

}

Any and all help is appreciated.

shizhen
  • 12,251
  • 9
  • 52
  • 88
Matthew M
  • 21
  • 5
  • There is not only one reason that cause this error, I suggest you go through this answer to get knowledge of reasons. https://stackoverflow.com/a/51579759/6891563 – Khemraj Sharma Jan 07 '19 at 12:22

1 Answers1

0

You should also put data tag into your XML code for the Coupon Item and set the viewModel class for CouponItem. Then the compiler could create CouponItemBindingImpl class. So try to update your coupon_item.xml file like below;

<layout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
            name="viewModel"
            type="path.to.your.viewmodel.class"/>
    </data>

    ... // your layout
</layout>
caneru
  • 391
  • 1
  • 2
  • 15
  • What exactly do you mean by set the viewModel class? I don't entirely understand what you mean – Matthew M Jan 07 '19 at 03:01
  • I have updated my answer. When you set your viewModel class path inside the data tag like above, compiler should generate the bindingImpl class accourding to the name of your xml file. Which is CouponItemBindingImpl i believe. – caneru Jan 07 '19 at 06:44
  • I'll try that. Thank you! – Matthew M Jan 07 '19 at 21:11