Reputation: 183
I'm trying to add some custom view using include
tag to my activity layout which using DataBinding. My custom view is using DataBinding as well. But I got crash on application start:
05-02 17:30:03.685 12595-12595/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.novachevskyi.databindingtest, PID: 12595
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.novachevskyi.databindingtest/com.novachevskyi.databindingtest.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.novachevskyi.databindingtest.databinding.CustomViewBinding.invalidateAll()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.novachevskyi.databindingtest.databinding.CustomViewBinding.invalidateAll()' on a null object reference
at com.novachevskyi.databindingtest.databinding.ActivityMainBinding.invalidateAll(ActivityMainBinding.java:41)
at com.novachevskyi.databindingtest.databinding.ActivityMainBinding.<init>(ActivityMainBinding.java:33)
at com.novachevskyi.databindingtest.databinding.ActivityMainBinding.bind(ActivityMainBinding.java:105)
at android.databinding.DataBinderMapper.getDataBinder(DataBinderMapper.java:11)
at android.databinding.DataBindingUtil.bind(DataBindingUtil.java:185)
at android.databinding.DataBindingUtil.bindToAddedViews(DataBindingUtil.java:299)
at android.databinding.DataBindingUtil.setContentView(DataBindingUtil.java:279)
at android.databinding.DataBindingUtil.setContentView(DataBindingUtil.java:261)
at com.novachevskyi.databindingtest.MainActivity.onCreate(MainActivity.java:11)
at android.app.Activity.performCreate(Activity.java:6251)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
MainActivity:
public class MainActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DataBindingUtil.setContentView(this, R.layout.activity_main);
}
}
CustomView:
public class CustomView extends LinearLayout {
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override protected void onFinishInflate() {
super.onFinishInflate();
DataBindingUtil.bind(this);
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="com.novachevskyi.databindingtest.MainActivity">
<include layout="@layout/custom_view"/>
</RelativeLayout>
</layout>
custom_view.xml:
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android">
<com.novachevskyi.databindingtest.CustomView
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:text="Hello World!"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</com.novachevskyi.databindingtest.CustomView>
</layout>
I've also created public repo with sample project: https://github.com/novachevskyi/DataBinding-issue
I was using data binding with com.android.tools.build:gradle:1.3.1
and now, when I've tried to upgrade build tools version to com.android.tools.build:gradle:2.1.0
, I'm facing such issue with all my views that contain include
xml tag. Will appreciate for any information about issue described above.
Upvotes: 12
Views: 6775
Reputation: 4442
For me, the crash was due using same id (@+id/progress_bar) in both include tag and in the layout file.
activity layout
<include **android:id="@+id/progress_bar"** layout="@layout/progress_bar" />
progress_bar.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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="@+id/progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
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>
when I change activity layout like this, it was fixed
<include **android:id="@+id/pb"** layout="@layout/progress_bar" />
Upvotes: 0
Reputation: 3057
In case anyone else makes the er..dumb mistake I did...
This error was happening to me when I mistakenly had two duplicate layout files, one using databinding, and the other not...
Removing the duplicate fixed the error for me.
Upvotes: 2
Reputation: 1479
@SeptimusX75's answer doesn't work, because DataBindingUtil.findBinding(this)
calls this.getTag(R.id.dataBinding)
internally to get the binding, but the tag hasn't been set yet when onFinishInflate
is called.
Instead, try to get the binding via this.getTag(R.id.dataBinding);
when you need the use the binding.
public class CustomView extends LinearLayout {
// ...
public CustomViewBinding binding;
// ...
public void setTitle(final String text) {
if (binding == null) {
binding = Objects.requireNonNull(getTag(R.id.dataBinding));
}
binding.title.setText(text);
}
}
Alternatively, set the binding manually from the activity before calling any method on the CustomView.
public class CustomView extends LinearLayout {
// ...
public CustomViewBinding binding;
// ...
public void setBinding(final CustomViewBinding binding) {
this.binding = binding;
}
}
public class MainActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CustomViewBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.customView.getRoot().setBinding(binding.customView);
}
}
Upvotes: -1
Reputation: 2195
I took a look at your project and ran it. I think the reason it is crashing is because of
@Override protected void onFinishInflate() {
super.onFinishInflate();
DataBindingUtil.bind(this);
}
if you remove DataBindingUtil.bind(this)
it will stop crashing. The reason being that the bind call is looking for a <layout>
surrounding the view but it can't find it so it throws an exception. Since the CustomView is calling bind on itself it is not surrounded by anything causing ViewDataBinding
to throw new IllegalArgumentException("View is not a binding layout")
I'm not entirely sure what you're trying to achieve but calling bind
inside of onFinishInflate
would be redundant since the activity is doing that for you when it binds the layout for the activity. If you require the binding within the CustomView
class you can do the following:
@Override protected void onAttachedToWindow() {
super.onAttachedToWindow();
CustomViewBinding binding = DataBindingUtil.findBinding(this);
}
Upvotes: 4