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.