12

I have created a custom view that uses data binding. It works fine in the application but it throws an error in the Android studio IDE.

DataBindingUtil.inflate throws an error because some of the fields in the binding are null in edit mode.

I can get around this by using isInEditMode and using normal inflate when it edit mode. However, that means that the preview is never accurate because no data is bound to the fields. If I try to skirt around data binding in edit mode and then poke in values directly then "why use data binding at all"?

Is there a way to use data binding in a custom view and get an accurate preview in the IDE?

public class HelpItem extends LinearLayoutCompat {
    private String mText = "Dog";
    private Drawable mDrawable;

    public HelpItem(Context context) {
        super(context);
        init(context, null, 0);
    }

    public HelpItem(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    public HelpItem(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }

    private void getStyleableAttributes(Context context, AttributeSet attrs) {
        if (null != attrs) {
            TypedArray attributes = context.obtainStyledAttributes(attrs,
                    R.styleable.HelpItem);
            mDrawable = attributes.getDrawable(R.styleable.HelpItem_helpItemIcon);
            mText = attributes.getString(R.styleable.HelpItem_helpItemText);

            attributes.recycle();
        }
    }
    private void init(Context context, AttributeSet attrs, @SuppressWarnings("unused") int defStyle) {
        getStyleableAttributes(context, attrs);
        LayoutInflater factory = LayoutInflater.from(context);
//        if (isInEditMode())
//            inflate(context, R.layout.view_help_item, this);
//        else {
            ViewHelpItemBinding binding = DataBindingUtil.inflate(factory, R.layout.view_help_item, this, true);
            binding.setText(mText);
            binding.setIcon(mDrawable);
            ImageView iv = binding.getRoot().findViewById(R.id.help_icon);
            if (null != iv) iv.setImageDrawable(mDrawable);
//        }
    }
}

Here is my custom view layout

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

    <data>

        <variable
            name="icon"
            type="android.graphics.drawable.Drawable" />
        <variable
            name="text"
            type="String" />

    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_marginTop="20dp"
        >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginBottom="12dp"
            >

            <ImageView
                android:id="@+id/help_icon"
                android:layout_width="70dp"
                android:layout_height="24dp"
                android:layout_gravity="center_vertical"
                app:icon="@{icon}"
                />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:layout_gravity="center_vertical"
                style="@style/ContactTextBold"
                android:text="@{text}"
                tools:text="@string/title_help_getting_started"
                android:textColor="@color/textColor"
                android:textSize="20sp"
                />

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="24dp"
                android:layout_gravity="center_vertical"
                android:layout_marginRight="20dp"
                app:srcCompat="@drawable/ic_baseline_keyboard_arrow_right_24px"
                />

        </LinearLayout>

        <include layout="@layout/seperator_view_gray" />

    </LinearLayout>
</layout>

Here is an example of how I include the custom view in a layout

            <com.apcon.intellaviewmobile.view.HelpItem
                android:id="@+id/getting_started"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:helpItemIcon="@drawable/ic_arrow_right"
                app:helpItemText="@string/title_help_getting_started"
                />

Here is the error being thrown in the IDE

java.lang.NullPointerException
    at com.apcon.intellaviewmobile.databinding.ViewHelpItemBindingImpl.<init>(ViewHelpItemBindingImpl.java:35)
    at com.apcon.intellaviewmobile.databinding.ViewHelpItemBindingImpl.<init>(ViewHelpItemBindingImpl.java:29)
    at com.apcon.intellaviewmobile.DataBinderMapperImpl.getDataBinder(DataBinderMapperImpl.java:118)
    at androidx.databinding.MergedDataBinderMapper.getDataBinder(MergedDataBinderMapper.java:74)
    at androidx.databinding.DataBindingUtil.bind(DataBindingUtil.java:199)
    at androidx.databinding.DataBindingUtil.bindToAddedViews(DataBindingUtil.java:327)
    at androidx.databinding.DataBindingUtil.inflate(DataBindingUtil.java:128)
    at androidx.databinding.DataBindingUtil.inflate(DataBindingUtil.java:95)
    at com.apcon.intellaviewmobile.view.HelpItem.init(HelpItem.java:51)
    at com.apcon.intellaviewmobile.view.HelpItem.<init>(HelpItem.java:27)
    at sun.reflect.GeneratedConstructorAccessor1708.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.jetbrains.android.uipreview.ViewLoader.createNewInstance(ViewLoader.java:403)
    at org.jetbrains.android.uipreview.ViewLoader.loadClass(ViewLoader.java:186)
    at org.jetbrains.android.uipreview.ViewLoader.loadView(ViewLoader.java:144)
    at com.android.tools.idea.rendering.LayoutlibCallbackImpl.loadView(LayoutlibCallbackImpl.java:309)
    at android.view.BridgeInflater.loadCustomView(BridgeInflater.java:418)
    at android.view.BridgeInflater.loadCustomView(BridgeInflater.java:429)
    at android.view.BridgeInflater.createViewFromTag(BridgeInflater.java:333)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
    at android.view.LayoutInflater.rInflate_Original(LayoutInflater.java:863)
    at android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:72)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:837)
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
    at android.view.LayoutInflater.rInflate_Original(LayoutInflater.java:866)
    at android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:72)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:837)
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:394)
    at com.android.layoutlib.bridge.impl.RenderSessionImpl.inflate(RenderSessionImpl.java:326)
    at com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:391)
    at com.android.tools.idea.layoutlib.LayoutLibrary.createSession(LayoutLibrary.java:195)
    at com.android.tools.idea.rendering.RenderTask.createRenderSession(RenderTask.java:540)
    at com.android.tools.idea.rendering.RenderTask.lambda$inflate$5(RenderTask.java:666)
    at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
    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)

Actual results: The IDE throws an error when previewing Desired results: To be able to use data binding in a custom view and see WYSIWIG preview in Android Studio.

1 Answers1

0

Android Studio Chipmunk doesnt have problem.
Android Studio Dolphin and Electric Eel have this CustomView databinding preview problem

According to this https://issuetracker.google.com/issues/260134720, Android Flamingo also doesnt have has problem, but it's still in beta

Im currently downgrade this Chipmunk version and it's working well

Android Studio Chipmunk | 2021.2.1 May 9, 2022

You can download archive from here https://developer.android.com/studio/archive

Linh
  • 57,942
  • 23
  • 262
  • 279