Giter Site home page Giter Site logo

binding-collection-adapter's Introduction

BindingCollectionAdapter

Maven Central

Easy way to bind collections to listviews and recyclerviews with the new Android Data Binding framework.

Download

If you are using androidx use version 4.0.0, this also uses databinding v2

implementation 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter:4.0.0'
implementation 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter-recyclerview:4.0.0'
implementation 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter-viewpager2:4.0.0'

or use the previous stable version

implementation 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter:2.2.0'
implementation 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter-recyclerview:2.2.0'

Usage

You need to provide your items and an ItemBinding to bind to the layout. You should use an ObservableList to automatically update your view based on list changes. However, you can use any List if you don't need that functionality.

public class ViewModel {
  public final ObservableList<String> items = new ObservableArrayList<>();
  public final ItemBinding<String> itemBinding = ItemBinding.of(BR.item, R.layout.item);
}

Then bind it to the collection view with app:items and app:itemBinding.

<!-- layout.xml -->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
      <import type="com.example.R" />
      <variable name="viewModel" type="com.example.ViewModel"/>
    </data>

    <ListView
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      app:items="@{viewModel.items}"
      app:itemBinding="@{viewModel.itemBinding}"/>

    <androidx.recyclerview.widget.RecyclerView
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
      app:items="@{viewModel.items}"
      app:itemBinding="@{viewModel.itemBinding}"/>

    <androidx.viewpager.widget.ViewPager
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      app:items="@{viewModel.items}"
      app:itemBinding="@{viewModel.itemBinding}"/>

    <Spinner
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      app:items="@{viewModel.items}"
      app:itemBinding="@{viewModel.itemBinding}"
      app:itemDropDownLayout="@{R.layout.item_dropdown}"/>
</layout>

In your item layout, the collection item will be bound to the variable with the name you passed into the ItemBinding.

<!-- item.xml -->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
      <variable name="item" type="String"/>
    </data>

    <TextView
      android:id="@+id/text"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="@{item}"/>
</layout>

Note: if app:itemBinding is null, then the adapter will be set to null. This is useful if you don't have an itemBinding right away (ex: need to wait till you load data). If you aren't seeing any views, make sure you have itemBinding defined!

Multiple View Types

You can use multiple view types by using OnItemBind instead. You can still bind it to the view with app:itemBinding.

public final OnItemBind<String> onItemBind = new OnItemBind<String>() {
  @Override
  public void onItemBind(ItemBinding itemBinding, int position, String item) {
    itemBinding.set(BR.item, position == 0 ? R.layout.item_header : R.layout.item);
  }
};

If you are binding to a ListView, you must also provide the number of item types you have with app:itemTypeCount="@{2}.

Note that onItemBind is called many times so you should not do any complex processing in there. If you don't need to bind an item at a specific position (a static footer for example) you can use ItemBinding.VAR_NONE as the variable id.

Bind Extra Variables

You can bind additional variables to items in the list with itemBinding.bindExtra(BR.extra, value). This is useful for components that you don't want the items themselves to care about. For example, you can implement an item click listener as such

public interface OnItemClickListener {
    void onItemClick(String item);
}

OnItemClickListener listener = ...;
ItemBinding<Item> itemBinding = ItemBinding.<Item>of(BR.item, R.layout.item)
    .bindExtra(BR.listener, listener);
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
      <variable name="item" type="String"/>
      <variable name="listener" type="OnItemClickListener"/>
    </data>

    <TextView
      android:id="@+id/text"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:onClick="@{() -> listener.onItemClick(item)}"
      android:text="@{item}"/>
</layout>

Additional Adapter Configuration

ListView

You can set a callback to give an id for each item in the list with

adapter.setItemIds(new BindingListViewAdapter.ItemIds<T>() {
  @Override
  public long getItemId(int position, T item) {
    return // Calculate item id.
  }
});

or by defining app:itemIds="@{itemIds}" in the ListView in your layout file. Setting this will make hasStableIds return true which can increase performance of data changes.

You can set a callback for isEnabled() as well with

adapter.setItemEnabled(new BindingListViewAdapter.ItemEnabled<T>() {
  @Override
  public boolean isEnabled(int position, T item) {
    return // Calculate if item is enabled.
  }
});

or by defining app:itemEnabled="@{itemEnabled}"in the ListView in you layout file.

ViewPager

You can set a callback to give a page title for each item in the list with

adapter.setPageTitles(new PageTitles<T>() {
  @Override
  public CharSequence getPageTitle(int position, T item) {
    return "Page Title";
  }
});

or by defining app:pageTitles="@{pageTitles}" in the ViewPager in your layout file.

RecyclerView

You can construct custom view holders with

adapter.setViewHolderFactory(new ViewHolderFactory() {
  @Override
  public RecyclerView.ViewHolder createViewHolder(ViewDataBinding binding) {
    return new MyCustomViewHolder(binding.getRoot());
  }
});

or by defining app:viewHolder="@{viewHolderFactory}" in the RecyclerView in your layout file.

Directly manipulating views

Data binding is awesome and all, but you may run into a case where you simply need to manipulate the views directly. You can do this without throwing away the whole of databinding by subclassing an existing BindingCollectionAdapter. You can then bind adapter in your layout to your subclass's class name to have it use that instead. Instead of overriding the normal adapter methods, you should override onCreateBinding() or onBindBinding() and call super allowing you to run code before and after those events and get access to the item view's binding.

public class MyRecyclerViewAdapter<T> extends BindingRecyclerViewAdapter<T> {

  @Override
  public ViewDataBinding onCreateBinding(LayoutInflater inflater, @LayoutRes int layoutId, ViewGroup viewGroup) {
    ViewDataBinding binding = super.onCreateBinding(inflater, layoutId, viewGroup);
    Log.d(TAG, "created binding: " + binding);
    return binding;
  }

  @Override
  public void onBindBinding(ViewDataBinding binding, int bindingVariable, @LayoutRes int layoutId, int position, T item) {
    super.onBindBinding(binding, bindingVariable, layoutId, position, item);
    Log.d(TAG, "bound binding: " + binding + " at position: " + position);
  }
}
<androidx.recyclerview.widget.RecyclerView
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
  app:items="@{viewModel.items}"
  app:itemBinding="@{viewModel.itemBinding}"
  app:adapter="@{viewModel.adapter}"/>

Note: databinding will re-evaluate expressions in your layout each time there is a data source change. If you are using a custom adapter you should ensure you are returning the same instance each time or your scroll position etc will not be preserved.

OnItemBind helpers

There are a few classes to help with common implementations of OnItemBind.

OnItemBindClass binds an item based on the class of the item in the list.

itemBind = new OnItemBindClass<>()
  .map(String.class, BR.name, R.layout.item_name)
  .map(Footer.class, ItemBinding.VAR_NONE, R.layout.item_footer)
  .map(Item.class, new OnItemBind<Item>() {
                       @Override
                       public void onItemBind(ItemBinding itemBinding, int position, Item item) {
                         itemBinding.clearExtras()
                                    .set(BR.item, position == 0 ? R.layout.item_header : R.layout.item)
                                    .bindExtra(BR.extra, (list.size() - 1) == position);
                       }
                     })
  .map(Object.class, ItemBinding.VAR_NONE, R.layout.item_other);

OnItemBindModel delegates to the items in the list themselves to determine the binding.

itemBind = new OnItemBindModel<Model>();

public class Model implements ItemBindingModel {
  @Override
  public void onItemBind(ItemBinding itemBinding) {
    itemBinding.set(BR.name, R.layout.item_name);
  }
}

MergeObservableList

There are many times you want to merge multiple data sources together. This can be as simple as adding headers and footers or as complex as concatenating multiple data sources. It is hard to manage these lists yourself since you have to take into account all items when updating a subset.

MergeObservableList solves this by giving you a "merged" view of your data sources.

ObservableList<String> data = new ObservableArrayList<>();
MergeObservableList<String> list = new MergeObservableList<>()
  .insertItem("Header")
  .insertList(data)
  .insertItem("Footer");

data.addAll(Arrays.asList("One", "Two"));
// list => ["Header", "One", "Two", "Footer"]
data.remove("One");
// list => ["Header", "Two", "Footer"]

DiffObservableList

Say you want to update list 'a' to list 'b' and you don't want to calculate what has changed between the two manually.

DiffObservableList builds off of DiffUtil to automatically calculate the changes between two lists.

DiffObservableList<Item> list = new DiffObservableList(new DiffObservableList.Callback<Item>() {
    @Override
    public boolean areItemsTheSame(Item oldItem, Item newItem) {
        return oldItem.id.equals(newItem.id);
    }

    @Override
    public boolean areContentsTheSame(Item oldItem, Item newItem) {
        return oldItem.value.equals(newItem.value);
    }
});

list.update(Arrays.asList(new Item("1", "a"), new Item("2", "b1")));
list.update(Arrays.asList(new Item("2", "b2"), new Item("3", "c"), new Item("4", "d"));

With large lists diffing might be too costly to run on the main thread. In that case you can calculate the diff on a background thread.

DiffObservableList<Item> list = new DiffObservableList(...);

// On background thread:
DiffUtil.DiffResult diffResult = list.calculateDiff(newItems);

// On main thread:
list.update(newItems, diffResult);

Paging

Paging is supported through the bindingcollectionadapter-paging artifact. First add it to your project

implementation 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter-paging:3.1.1'

Then bind a PagedList and DiffUtil.ItemCallback.

LiveData<PagedList<Item>> pagedList = new LivePagedListBuilder<>(..., 20);
DiffUtil.ItemCallback<Item> diff = ...;
<androidx.recyclerview.widget.RecyclerView
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
  app:items="@{pagedList}"
  app:itemBinding="@{itemBinding}"
  app:diffConfig="@{diff}" />

Known Issues

Cannot Resolve the libraries @BindingAdapter's

This is likely because you are using the android-apt plugin which broke this in previous versions. Update to 1.6+ to fix it.

View's adapter is null

If you attempt to retrieve an adapter from a view right after binding it you may find it is null. This is because databinding waits for the next draw pass to run to batch up changes. You can force it to run immediately by calling binding.executePendingBindings().

LiveData not working

Live data support has been added in 2.3.0-beta3 and 3.0.0-beta3 (androidx). For most cases it should 'just work'. However, it uses a bit of reflection under the hood and you'll have to call adapter.setLifecycleOwner(owner) if your containing view does not use databinding. This will be fixed whenever this issue gets resolved.

License

Copyright 2015 Evan Tatarka

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

binding-collection-adapter's People

Contributors

arberg avatar dev-il avatar evant avatar janbina avatar kamiox avatar leofernandesmo avatar naitbit avatar nwagu avatar okhoshi avatar s0nerik avatar saleehk avatar timoptr avatar truenight avatar villesinisalo avatar vkotovv avatar wongcain avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

binding-collection-adapter's Issues

Typo in README

Is:

compile 'me.tatarka.bindingcollectionadaper:bindingcollectionadapter:1.0.0'
compile 'me.tatarka.bindingcollectionadaper:bindingcollectionadapter-recyclerview:1.0.0'

should be:

compile 'me.tatarka.bindingcollectionadapter:bindingcollectionadapter:1.0.0'
compile 'me.tatarka.bindingcollectionadapter:bindingcollectionadapter-recyclerview:1.0.0'

Copy-paste caught me off guard : )

How to bind an adapter to an individual cell

For my individual item.xml, I need direct programmatic manipulation. For manipulation of the ListView, I'm using a BindingListViewAdapter, per the introduction to this library. I need direct access to the child views in my individual cells, is that possible? I've tried attaching an activity like normal, but onCreate never fires for any of them.

also NullPointerException

Simple demo:
list.xml
<RecyclerView bind:items="items" bind:itemView="itemView"/>
i use it ok.
but when i use
<include layout:list.xml bind:listViewModel="listViewModel"/>
it throw NullPointerException

E/AndroidRuntime: FATAL EXCEPTION: main java.lang.NullPointerException at me.tatarka.bindingcollectionadapter.ItemViewArg.select(ItemViewArg.java:29) at me.tatarka.bindingcollectionadapter.BindingRecyclerViewAdapter.getItemViewType(BindingRecyclerViewAdapter.java:157) at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4960) at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4913) at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2029) at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1414) at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1377) at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:578) at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3260) at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java:2788) at android.view.View.measure(View.java:15518)

just nest listView or RecyclerView in

how to fix it? thanks very much

Picture chaos in listview with BindingCollectionAdapter

Excuseme, My English is not good. I use the BindingCollectionAdapter to my project, then i bindingdata in the listview, it has image and text. I use Glide to load image, when the data is more, it will appear Picture chaos. I shoud how to solve the problem, I hope you can help me

Enhancement suggestion: allow usage of custom ViewHolder implementation

While using your library in combination with RecyclerView I came across this article as I was implementing my own multi-selection mechanism: https://www.bignerdranch.com/blog/recyclerview-part-2-choice-modes/

They suggest subclassing RecyclerView.ViewHolder to give the indication of the selected state a more polished feel. Using the library, there is unfortunately no way to do that as of now.

I am also using this library in my project: https://github.com/mikepenz/MaterialDrawer

The items in the drawer are also being displayed in a RecyclerView. To give the user the possibility to fully customize or create an own implementation of an item inside the drawer, they give you the following pattern to work with, where BaseViewHolder and ViewHolderFactory are classes from the library:

public ViewHolderFactory<ViewHolder> getFactory() {
    return new ItemFactory();
}

public static class ItemFactory implements ViewHolderFactory<ViewHolder> {

    @Override
    public ViewHolder create(View v) {
        return new ViewHolder(v);
    }
}

public static class ViewHolder extends BaseViewHolder {
    // custom variables here

    public ViewHolder(View view) {
        super(view);
        // custom code here
    }
}

If the BindingRecyclerViewAdapter would provide some methods along those lines to override instead of directly instantiating the standard RecyclerView.ViewHolder directly, it would be easy to use a custom ViewHolder.

I would love to hear back from you and get your thoughts on the matter.

Build error

I'm trying to add the library to my project and I can't seem to make it work, It shows this build error

Error:(24, 9) error: constructor ViewDataBinding in class ViewDataBinding cannot be applied to given types;
required: DataBindingComponent,View,int
found: View,int
reason: actual and formal argument lists differ in length
Error:(25, 35) error: no suitable method found for mapBindings(View,int,IncludedLayouts,SparseIntArray)
method ViewDataBinding.mapBindings(DataBindingComponent,View,int,IncludedLayouts,SparseIntArray) is not applicable
(actual and formal argument lists differ in length)
method ViewDataBinding.mapBindings(DataBindingComponent,View[],int,IncludedLayouts,SparseIntArray) is not applicable
(actual and formal argument lists differ in length)

The error is pointing to the generated binding class

public ActivityMainBinding(View root) {
        super(root, 0); //1
        final Object[] bindings = mapBindings(root, 3, sIncludes, sViewsWithIds); //2
        this.fab = (android.support.design.widget.FloatingActionButton) bindings[2];
        this.mboundView0 = (android.support.design.widget.CoordinatorLayout) bindings[0];
        this.mboundView0.setTag(null);
        this.toolbar = (android.support.v7.widget.Toolbar) bindings[1];
        setRootTag(root);
        invalidateAll();
}

NullPointerException when getting layoutRes()

I'm not sure if I have used the library correctly or not. Please troubleshoot, thanks!

java.lang.NullPointerException
     at me.tatarka.bindingcollectionadapter.ItemViewArg.layoutRes(ItemViewArg.java:37)
     at me.tatarka.bindingcollectionadapter.BindingViewPagerAdapter.instantiateItem(BindingViewPagerAdapter.java:99)
     at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:870)
     at android.support.v4.view.ViewPager.populate(ViewPager.java:1020)
     at android.support.v4.view.ViewPager.populate(ViewPager.java:952)
     at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1474)
     at android.view.View.measure(View.java:16497)
     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
     at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
     at android.view.View.measure(View.java:16497)
     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
     at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
     at android.support.v7.internal.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:124)
     at android.view.View.measure(View.java:16497)
     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
     at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1404)
     at android.widget.LinearLayout.measureVertical(LinearLayout.java:695)
     at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
     at android.view.View.measure(View.java:16497)
     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
     at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
     at android.view.View.measure(View.java:16497)
     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
     at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1404)
     at android.widget.LinearLayout.measureVertical(LinearLayout.java:695)
     at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
     at android.view.View.measure(View.java:16497)
     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
     at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
     at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2291)
     at android.view.View.measure(View.java:16497)
     at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1912)
     at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1109)
     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1291)
     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:996)
     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5600)
     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
     at android.view.Choreographer.doCallbacks(Choreographer.java:574)
     at android.view.Choreographer.doFrame(Choreographer.java:544)
     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
     at android.os.Handler.handleCallback(Handler.java:733)
     at android.os.Handler.dispatchMessage(Handler.java:95)
     at android.os.Looper.loop(Looper.java:136)
     at android.app.ActivityThread.main(ActivityThread.java:5001)
     at java.lang.reflect.Method.invokeNative(Native Method)
     at java.lang.reflect.Method.invoke(Method.java:515)
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
     at dalvik.system.NativeStart.main(Native Method)

Activity layout file:

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

  <data>

    <variable
        name="viewModel"
        type="com.example.viewmodel.WalkthroughViewModel"/>
  </data>

  <FrameLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent">

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:itemView="@{viewModel.itemView}"
        app:items="@{viewModel.items}"/>

    <com.viewpagerindicator.CirclePageIndicator
        android:id="@+id/indicator"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:padding="10dip"/>
  </FrameLayout>
</layout>

Item layout file:

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

  <data>

    <variable
        name="item"
        type="com.example.viewmodel.WalkthroughPageViewModel"/>
  </data>

  <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:layout_margin="@dimen/spacing_large"
      android:gravity="center_horizontal"
      android:orientation="vertical">


    <ImageView
        android:id="@+id/avatar"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_gravity="center"
        android:layout_weight="1"
        android:scaleType="centerInside"
        android:src="@{item.image}"
        tools:src="@drawable/reactnative_assets_walkthrough1"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/spacing_large"
        android:gravity="center"
        android:textColor="@color/blue_light"
        android:textSize="@dimen/font_large"
        android:text="@{item.title}"
        tools:text="@string/walkthrough_title1"/>

    <View
        android:layout_width="100dp"
        android:layout_height="1dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="@dimen/spacing_large"
        android:background="@color/blue_light"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/spacing_large"
        android:text="@{item.description}"
        tools:text="@string/walkthrough_description1"
        />
  </LinearLayout>
</layout>

The code to bind data:

ActivityWalkthroughBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_walkthrough);
    binding.executePendingBindings();
    binding.indicator.setViewPager(binding.viewpager);
    WalkthroughViewModel viewModel = new WalkthroughViewModel(Arrays.asList(
        new WalkthroughPageViewModel("title1", "description2", getResources().getDrawable(R.drawable.reactnative_assets_walkthrough1), false),
        new WalkthroughPageViewModel("title2", "description2", getResources().getDrawable(R.drawable.reactnative_assets_walkthrough2), false)
    ));
    binding.setViewModel(viewModel);

How to access the child binding from parent.

I have an activity which has a ViewpagerViewBinding.

        <android.support.v4.view.ViewPager
            android:id="@+id/pager"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            app:itemView="@{viewModel.singleItemView}"
            app:items="@{viewModel.items}"
            app:pageTitles="@{viewModel.pageTitles}" />

The singleItemView of ViewPager is a SwipeRefreshLayout with a RecyclerView.

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipeRefresh"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:itemView="@{item.itemView}"
            app:items="@{item.items}"
            app:layoutManager="@{LayoutManagers.linear()}" />

    </android.support.v4.widget.SwipeRefreshLayout>

binding.pager doesn't have access to swipeRefresh or recycler. How to access SwipeRefreshLayout or RecyclerView from activity so that I can implement refresh behaviour and endless scrolling.

Using an item animator results in crashes in v1.+

If using verbatim, everything works great. If I add an item animator to the recyclerview, in 1.+ it crashes the app, and on 2.0.0-beta2 works.
The test is as follows:

  1. Attach the item animator (I'm using jp.wasabeef.recyclerview.animators.OvershootInRightAnimator).
  2. Load the list. Everything works fine.
  3. Reload the list (I do this with a SwipeRefreshLayout).
  4. When reloading the list, the items are cleared from the ObservableList, and recreated. At this step, it reloads ok, but in logcat I see lots of this:

View: isRecyclable decremented below 0: unmatched pair of setIsRecyable() calls for ViewHolder{8da5b74 position=0 id=-1, oldPos=-1, pLpos:-1}```

I'm getting this on 2.0.0-beta2 too.

  1. If I reload again, the app crashes with the following error:

java.lang.IllegalArgumentException: Called attach on a child which is not detached: ViewHolder{7c63ec8 position=0 id=-1, oldPos=-1, pLpos:-1 no parent} at android.support.v7.widget.RecyclerView$5.attachViewToParent(RecyclerView.java:692) at android.support.v7.widget.ChildHelper.attachViewToParent(ChildHelper.java:239) at android.support.v7.widget.RecyclerView$LayoutManager.addViewInt(RecyclerView.java:7096) at android.support.v7.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:7073) at android.support.v7.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:7061) at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1428) at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1377) at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:578) at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3315) at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3124) at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3568) at android.view.View.layout(View.java:16636) at android.view.ViewGroup.layout(ViewGroup.java:5437) at android.support.v4.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:613)

Data bidning error

***_/ data binding error ***_msg:Cannot find the setter for attribute 'app:items' with parameter type android.databinding.ObservableList<'java.lang.Object'>.

In case of using multiple views adapter
Started at 0.11 in 0.10 works fine

BaseAdapter#isEnabled support

Hey,

I was wandering is it possible to easly use BaseAdapter#isEnabled function. I was looking at the source code of the BindingListViewAdapter however no straight forward solution comes into my mind. Any hints?

Setting ViewPager in ViewPagerIndicator?

I have a ViewPager setup and working well with this adapter However, I haven't found a good solution for setting the view pager in the ViewPagerIndicator I'm using (https://github.com/JakeWharton/ViewPagerIndicator, which has a method setViewPager(ViewPager view)). I tried setting the viewPager after inflating the binding layout, but that class errors out that there is no adapter set. I have that adapter defined for the ViewPager in XML as "app:adapter="@{viewModel.itemsFactory}"". Is there a good way to bind/connect these views?

No good way to replace the list without losing your position.

If you want to replace the entire contents of the list and just issue a notifyDataSetChanged() there is no good way to do that. If you remove all items from the observable collection and re-add them, you list will scroll up to the top since at one point it had no items. Calling setItems() on the adapter will also do the same thing.

Adding takeView and dropView on ItemViewModel

I'm using MVVM architecture in my project, My ViewModel is a subclass of this class:

public class MvvmViewModel<V extends MvvmView> {

    private V mView;

    public MvvmViewModel() { }

    @NonNull
    public V getView() {
        return mView;
    }

    @CallSuper
    public void takeView(V view) {
        mView = view;
    }

    @CallSuper
    public void dropView() {
         mView = null;
    }

}

In a fragment I do it like this

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    mBinding = DataBindingUtil.inflate(inflater, R.layout.orders_fragment_view, container, false);
    mBinding.setViewModel(mViewModel);
    mViewModel.takeView(this);
    return mBinding.getRoot();
}

@Override
public void onDestroyView() {
    super.onDestroyView();
    mViewModel.dropView();
}

My question is where should I call takeView and dropView?, Right now I call takeView on onBindBinding still not sure where to call dropView.

@Override
public void onBindBinding(ViewDataBinding binding, int bindingVariable, @LayoutRes int layoutRes, int position, T item) {
    super.onBindBinding(binding, bindingVariable, layoutRes, position, item);
    // item.takeView(binding.getRoot());
}

Cannot find the setter for attribute 'app:items' with parameter type android.databinding.ObservableList<PhotoItem> on android.support.v7.widget.RecyclerView

I'm trying to create a RecyclerView that binds to a list of `PhotoItem' but I keep getting the above error when compiling. What am I possibly missing?

My ViewModel class:

public class PhotoViewModel extends CoreViewModel {
    public final ObservableList<PhotoItem> items = new ObservableArrayList<>();
    public final ItemView itemView = ItemView.of(BR.item, R.layout.item_photo);
}

My PhotoItem class:

public class PhotoItem extends CoreViewModel{
    protected String url;

    @Bindable
    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
        notifyPropertyChanged(BR.url);
    }
}

My custom adapter

public class PhotoAdapter<PhotoItem> extends BindingRecyclerViewAdapter<PhotoItem> implements AdapterView.OnItemClickListener{

    public PhotoAdapter(@NonNull ItemViewArg<PhotoItem> arg) {
        super(arg);
    }

    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
        ResourceUtil.showToast(view.getContext(), "position: " + position);
    }
}

The RecyclerView

<android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:adapter="@{photoAdapter}"
            app:layoutManager="@{LayoutManagers.grid(4)}"
            app:items="@{viewModel.items}"
            app:itemView="@{viewModel.itemView}" />

Databinding rc2 causes crashes when using LayoutManager helpers

java.lang.IllegalStateException: Required DataBindingComponent is null in class FragmentLiveBinding. A BindingAdapter in me.tatarka.bindingcollectionadapter.BindingCollectionAdapters is not static and requires an object to use, retrieved from the DataBindingComponent. If you don't use an inflation method taking a DataBindingComponent, use DataBindingUtil.setDefaultComponent or make all BindingAdapter methods static

Only change being the bump from rc1 -> rc2

LayoutManager from binding is not restoring position

Hi, I'm using this library and I set the LayoutManager with binding like this app:layoutManager="@{LayoutManagers.linear()}"
Unfortunately, when I rotate the screen, or if I re-attach the Fragment again, the new LayoutManager is created, and the RecyclerView is scrolled on top.

If I set the LayoutManager from the code (in Fragment in onActivityCreated method), the RecyclerView has the same position after rotation or after re-attaching.

Did I miss something? Do you have any suggestion how to handle this?

Otherwise I'm really enjoying this library!

Null items not working in 0.13

java.lang.NullPointerException: collection == null
     at java.util.ArrayList.<init>(ArrayList.java:94)
     at me.tatarka.bindingcollectionadapter.Utils.getListFromCollection(Utils.java:83)
     at me.tatarka.bindingcollectionadapter.BindingViewPagerAdapter.setItems(BindingViewPagerAdapter.java:66)

Items in RecyclerView not properly recycled

Hi and first of all thx for this very useful library. That being said, I think there's a bug when using it with a RecyclerView.

So, the thing is, I have a RecyclerView whose items are forms made of a bunch of EditTexts. Those forms are actually linked to a ViewModel so when I write something in one of the EditTexts, it updates my viewModels accordingly thx to DataBinding.
This seems to work, my ViewModel instances are correctly being updated so there isn't the problem.

Let's now say I have 3 items in my RecyclerView, their first EditText being initialized with incremented string + numbers on the go (so "item 1", "item 2", "item 3"). Scrolling from top to bottom isn't a problem but when scrolling back up, the EditText's content get all messed up.
My attempt at an explanation of this would be that the items that are being recycled when disappearing from the screen are not being "debinded" from their ViewModel. Therefore, when scrolling, the values of the first items are being updated because they are becoming the last items (which are being initialized on the go).

Scenario:

  • Initializing first item, (EditText = "item 1", updating the ViewModel),
  • Scrolling down,
  • Recycling first item, (seemingly not "debinding" it's viewmodel),
  • Reusing first item as third item,
  • Initializing third item (EditText = "item 3") still binded to the first item's ViewModel (since the third item IS the first item because that's how a RecyclerView works),
  • Updating third item's ViewModel which is still binded to the first item,
  • Scrolling back up to the first item,
  • "item 3" is now written in the first item's editText because its viewModel said so.

Hope it helps, if you need a code example or something, just ask, I'll see what I can do.

**.databinding no exist

In my demo. all databinding can import automatically. but when it ruuning
Error msg show that :
Error:(10, 44) 错误: 程序包com.xhyy.lxr.listviewdb1.databinding不存在(“不存在”means not exist)

ExpandableListView support

Hi. I want to use your library with ExpandableListView. But changing ListView to ExpandableListView does not work. How can I do that?

ListView onItemClickListener not work

I'll try to explain my app:
I have some Json-> POJO Model with multiple arrays of items implementing parcelable. I'm able to set one of this list to intent data without creating items twice. Data are taken with ViewModel which is created simultaneously with activity. ViewModel creates ViewDataModel(model with observable array list of json models and ItemView property) from parcelable intent data. But i need to navigate forward to another activity when listview item is clicked.

So i would have to propagate Activity to ViewModel -> ViewModelData -> ViewModelDataItem(My json model). Am i only one who seeing this like a bad idea?

So my idea was to add onItemClickListener in my Activity where i have Bindings for listview, that would be perfect solution. But even if i set listener, it's never called. I don't exactly know why. But set data to my bindings loads the listview items. Probably i miss the concept.

Could you please explain how to properly set OnItemClickListener or do what i want with the most clean solution?

Binding events problem

If you try to bind event in item you will get NullPointerException while building project.

To repeat this issue you can add android:onClick="@{item.onClick}" to any view in item.xml
and method

  public void onClick(View view){
        checked = !checked;
        notifyPropertyChanged(me.tatarka.bindingcollectionadapter.sample.BR.checked);
    }

in ItemViewModel.java

Support for HintView in Spinner

What do you think about adding support for hint view in Spinner?

<Spinner
                android:id="@+id/list"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:dropDownHintView="@{viewModel.dropDownHintView}"
                app:dropDownItemView="@{viewModel.dropDownItemView}"
                app:itemIds="@{viewModel.itemIds}"
                app:itemView="@{viewModel.singleItemView}"
                app:items="@{viewModel.items}" />

POC code (not fully tested) is on my branch:
https://github.com/kamiox/binding-collection-adapter/tree/spinner-hintview

app:itemDropdownView ?

For a Spinner etc, would it make more sense to replace itemView.setLayoutRes(BindingListViewAdapter.DROP_DOWN_LAYOUT, R.layout.item_dropdown); with just binding directly in the XML?

<Spinner
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      app:items="@{viewModel.items}"
      app:itemView="@{viewModel.itemView}"
      app:itemDropdownView="@{viewModel.itemDropdownView}"/>

Resources$NotFoundException: Resource ID #0x0

android.content.res.Resources$NotFoundException: Resource ID #0x0
at android.content.res.Resources.getValue(Resources.java:1981)
at android.content.res.Resources.loadXmlResourceParser(Resources.java:3187)
at android.content.res.Resources.getLayout(Resources.java:1797)
at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
at android.databinding.DataBindingUtil.inflate(DataBindingUtil.java:116)
at android.databinding.DataBindingUtil.inflate(DataBindingUtil.java:88)
at com.common.bindingcollectionadapter.BindingRecyclerViewAdapter.onCreateBinding(BindingRecyclerViewAdapter.java:68)
at com.common.bindingcollectionadapter.BindingRecyclerViewAdapter.onCreateViewHolder(BindingRecyclerViewAdapter.java:107)
at com.common.bindingcollectionadapter.BindingRecyclerViewAdapter.onCreateViewHolder(BindingRecyclerViewAdapter.java:24)
at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:4385)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3700)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3609)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1859)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1311)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1274)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:510)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2118)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:2415)
at android.view.View.layout(View.java:15204)
at android.view.ViewGroup.layout(ViewGroup.java:4793)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1076)
at android.view.View.layout(View.java:15204)
at android.view.ViewGroup.layout(ViewGroup.java:4793)
at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
at android.view.View.layout(View.java:15204)
at android.view.ViewGroup.layout(ViewGroup.java:4793)
at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
at android.view.View.layout(View.java:15204)
at android.view.ViewGroup.layout(ViewGroup.java:4793)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1076)
at android.view.View.layout(View.java:15204)
at android.view.ViewGroup.layout(ViewGroup.java:4793)
at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
at android.view.View.layout(View.java:15204)
at android.view.ViewGroup.layout(ViewGroup.java:4793)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1677)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1531)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1440)
at android.view.View.layout(View.java:15204)
at android.view.ViewGroup.layout(ViewGroup.java:4793)
at me.imid.swipebacklayout.lib.SwipeBackLayout.onLayout(SwipeBackLayout.java:386)
at android.view.View.layout(View.java:15204)
at android.view.ViewGroup.layout(ViewGroup.java:4793)
at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
at android.view.View.layout(View.java:15204)
at android.view.ViewGroup.layout(ViewGroup.java:4793)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2257)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2004)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1246)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6350)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:791)
at android.view.Choreographer.doCallbacks(Choreographer.java:591)
at android.view.Choreographer.doFrame(Choreographer.java:561)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:777)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5454)

在使用三星,小米部分手机时,会出现两次调用BindingRecyclerViewAdapters中的setAdapter(RecyclerView recyclerView, ItemViewArg arg, List items)方法,第一次调用arg和item都为null,第二次调用才有正常参数。所以报以上错误。
所以我修改为
public static void setAdapter(RecyclerView recyclerView, ItemViewArg arg, List items) {
if (null == items || items.isEmpty()) return;
setAdapter(recyclerView, arg, items, BindingRecyclerViewAdapterFactory.DEFAULT, null);
}
就可以正常运行了。

In the use of the Samsung, xiaomi mobile phone, two calls to the BindingRecyclerViewAdapters, setAdapter(RecyclerView recyclerView, Arg ItemViewArg, List items)
the first call to Arg and item is null, the second call to the normal reference number. So the above error report.
So I changed to
Public static void setAdapter (RecyclerView recyclerView, ItemViewArg Arg, List items) {
If (null = = items items.isEmpty (return) ||);
SetAdapter (recyclerView, Arg, items, BindingRecyclerViewAdapterFactory.DEFAULT, null);
}
Can the normal operation.

IllegalStateException with No Bindings

I realize this is a bit counter intuitive to the intent of the library, but I ran into the following exception when I had no bindings defined in my Item view model:

java.lang.IllegalStateException: Could not bind variable '3' in layout '<...>/item'
    at me.tatarka.bindingcollectionadapter.BindingCollectionAdapters.throwMissingVariable(BindingCollectionAdapters.java:276)

I ran into the exception while stubbing classes and layouts out to test the library. When I added a binding in my layout, everything worked fine. It seems like things should still work even if I decide not to have any bindings in my item layouts.

Suggestion for documentation improvement

I'd like to suggest that the readme is expanded to list the benefits of using this library versus the features provided by the core databinding library. As it stands, the purpose of the library isn't very clear.

If the main claim is that "it makes things easier", perhaps a "before and after" example would be beneficial.
If it adds functionality (such as allowing to choose from multiple itemViews) this should be stressed, imho.

(The other day I was trying to convince a colleague that he should be using this library, but he insisted that one needs nothing else besides the default databinding library to create bindings for RecyclerView etc. )

ClassNotFoundException after switching from 1.2.0-beta1 to 1.2.0

After updating to the most recent version this error occurs with the following log output at compile-time:

Error:Could not read Binding properties intermediate file. C:\Users\Robert\AndroidStudioProjects\MusicMate\app\build\intermediates\exploded-aar\com.android.databinding\adapters\1.1\jars\classes.jar java.lang.ClassNotFoundException: android.databinding.annotationprocessor.ProcessExpressions$IntermediateV2 at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348) at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:628) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1620) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1521) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1781) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373) at android.databinding.tool.util.GenerationalClassUtil.fromInputStream(GenerationalClassUtil.java:152) at android.databinding.tool.util.GenerationalClassUtil.loadFomZipFile(GenerationalClassUtil.java:131) at android.databinding.tool.util.GenerationalClassUtil.buildCache(GenerationalClassUtil.java:81) at android.databinding.tool.util.GenerationalClassUtil.loadObjects(GenerationalClassUtil.java:51) at android.databinding.tool.store.SetterStore.load(SetterStore.java:159) at android.databinding.tool.store.SetterStore.get(SetterStore.java:152) at android.databinding.annotationprocessor.ProcessMethodAdapters.onHandleStep(ProcessMethodAdapters.java:59) at android.databinding.annotationprocessor.ProcessDataBinding$ProcessingStep.runStep(ProcessDataBinding.java:148) at android.databinding.annotationprocessor.ProcessDataBinding$ProcessingStep.access$000(ProcessDataBinding.java:133) at android.databinding.annotationprocessor.ProcessDataBinding.process(ProcessDataBinding.java:63) at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794) at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:705) at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91) at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035) at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176) at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170) at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856) at com.sun.tools.javac.main.Main.compile(Main.java:523) at com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:129) at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:138) at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:45) at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:33) at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.delegateAndHandleErrors(NormalizingJavaCompiler.java:101) at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:50) at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:36) at org.gradle.api.internal.tasks.compile.CleaningJavaCompilerSupport.execute(CleaningJavaCompilerSupport.java:34) at org.gradle.api.internal.tasks.compile.CleaningJavaCompilerSupport.execute(CleaningJavaCompilerSupport.java:25) at org.gradle.api.tasks.compile.JavaCompile.performCompilation(JavaCompile.java:157) at org.gradle.api.tasks.compile.JavaCompile.compile(JavaCompile.java:139) at org.gradle.api.tasks.compile.JavaCompile.compile(JavaCompile.java:93) at sun.reflect.GeneratedMethodAccessor1311.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.doExecute(AnnotationProcessingTaskFactory.java:244) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:220) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.execute(AnnotationProcessingTaskFactory.java:231) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:209) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46) at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35) at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64) at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58) at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52) at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52) at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53) at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43) at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:203) at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:185) at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:62) at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:50) at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:25) at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:110) at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37) at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37) at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23) at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43) at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32) at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37) at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30) at org.gradle.initialization.DefaultGradleLauncher$4.run(DefaultGradleLauncher.java:154) at org.gradle.internal.Factories$1.create(Factories.java:22) at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90) at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:52) at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:151) at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:32) at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:99) at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:93) at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90) at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:62) at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:93) at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:82) at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:94) at org.gradle.tooling.internal.provider.runner.BuildModelActionRunner.run(BuildModelActionRunner.java:46) at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35) at org.gradle.tooling.internal.provider.runner.SubscribableBuildActionRunner.run(SubscribableBuildActionRunner.java:58) at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35) at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:43) at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28) at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:77) at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:47) at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:52) at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74) at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72) at org.gradle.util.Swapper.swap(Swapper.java:38) at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.health.DaemonHealthTracker.execute(DaemonHealthTracker.java:47) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:66) at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:71) at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.health.HintGCAfterBuild.execute(HintGCAfterBuild.java:41) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50) at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:246) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54) at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40) 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) Error:Execution failed for task ':app:compileDebugJavaWithJavac'. java.lang.RuntimeException: failure, see logs for details. Could not read Binding properties intermediate file. C:\Users\Robert\AndroidStudioProjects\MusicMate\app\build\intermediates\exploded-aar\com.android.databinding\adapters\1.1\jars\classes.jar java.lang.ClassNotFoundException: android.databinding.annotationprocessor.ProcessExpressions$IntermediateV2 at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348) at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:628) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1620) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1521) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1781) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373) at android.databinding.tool.util.GenerationalClassUtil.fromInputStream(GenerationalClassUtil.java:152) at android.databinding.tool.util.GenerationalClassUtil.loadFomZipFile(GenerationalClassUtil.java:131) at android.databinding.tool.util.GenerationalClassUtil.buildCache(GenerationalClassUtil.java:81) at android.databinding.tool.util.GenerationalClassUtil.loadObjects(GenerationalClassUtil.java:51) at android.databinding.tool.store.SetterStore.load(SetterStore.java:159) at android.databinding.tool.store.SetterStore.get(SetterStore.java:152) at android.databinding.annotationprocessor.ProcessMethodAdapters.onHandleStep(ProcessMethodAdapters.java:59) at android.databinding.annotationprocessor.ProcessDataBinding$ProcessingStep.runStep(ProcessDataBinding.java:148) at android.databinding.annotationprocessor.ProcessDataBinding$ProcessingStep.access$000(ProcessDataBinding.java:133) at android.databinding.annotationprocessor.ProcessDataBinding.process(ProcessDataBinding.java:63) at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794) at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:705) at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91) at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035) at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176) at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170) at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856) at com.sun.tools.javac.main.Main.compile(Main.java:523) at com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:129) at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:138) at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:45) at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:33) at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.delegateAndHandleErrors(NormalizingJavaCompiler.java:101) at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:50) at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:36) at org.gradle.api.internal.tasks.compile.CleaningJavaCompilerSupport.execute(CleaningJavaCompilerSupport.java:34) at org.gradle.api.internal.tasks.compile.CleaningJavaCompilerSupport.execute(CleaningJavaCompilerSupport.java:25) at org.gradle.api.tasks.compile.JavaCompile.performCompilation(JavaCompile.java:157) at org.gradle.api.tasks.compile.JavaCompile.compile(JavaCompile.java:139) at org.gradle.api.tasks.compile.JavaCompile.compile(JavaCompile.java:93) at sun.reflect.GeneratedMethodAccessor1311.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.doExecute(AnnotationProcessingTaskFactory.java:244) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:220) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.execute(AnnotationProcessingTaskFactory.java:231) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:209) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46) at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35) at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64) at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58) at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52) at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52) at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53) at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43) at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:203) at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:185) at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:62) at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:50) at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:25) at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:110) at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37) at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37) at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23) at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43) at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32) at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37) at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30) at org.gradle.initialization.DefaultGradleLauncher$4.run(DefaultGradleLauncher.java:154) at org.gradle.internal.Factories$1.create(Factories.java:22) at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90) at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:52) at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:151) at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:32) at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:99) at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:93) at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90) at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:62) at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:93) at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:82) at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:94) at org.gradle.tooling.internal.provider.runner.BuildModelActionRunner.run(BuildModelActionRunner.java:46) at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35) at org.gradle.tooling.internal.provider.runner.SubscribableBuildActionRunner.run(SubscribableBuildActionRunner.java:58) at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35) at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:43) at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28) at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:77) at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:47) at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:52) at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74) at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72) at org.gradle.util.Swapper.swap(Swapper.java:38) at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.health.DaemonHealthTracker.execute(DaemonHealthTracker.java:47) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:66) at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:71) at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.health.HintGCAfterBuild.execute(HintGCAfterBuild.java:41) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50) at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:246) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54) at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40) 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)

The problem seems to be the update from adapters-1.0-rc3 to adapters-1.1, but other than that I have no clue what exactly is causing the problem.

I'm using Android Studio 1.5.1 and Gradle 2.8.

I know this is most likely not directly related to your library, but I have just started using databinding and hence no idea what to look for as cause, and googling also yielded no result. Any help is greatly appreciated and thanks im advance!

AssertJ should be test dependency

The build.gradle of the library defines the AssertJ dependency in compile scope instead of test scope. I guess this is a mistake, because this way AssertJ will end up in users' APKs.

To work around this, i currently exclude AssertJ from the transitive dependencies of this library:

compile('me.tatarka:bindingcollectionadapter:0.13') {
    exclude group: "org.assertj"
}

ItemViewSelector selecting wrong layout

Ok so here is how I have this setup. And with this setup, if you scroll the list view the items changes between the different layouts.

public class TimelineVM {
    public final ObservableList<NotificationAbstract> items = new ObservableArrayList<>();
    public final ItemViewSelector<NotificationAbstract> itemView = new BaseItemViewSelector<NotificationAbstract>() {
        @Override
        public void select(ItemView itemView, int position, NotificationAbstract item) {
            if (item instanceof ChatNotification) {
                itemView.set(BR.item, R.layout.notification_chat_layout);
            } else if (item instanceof TrackNotification) {
                itemView.set(BR.item, R.layout.notification_track_layout);
            } else if (item instanceof StatusNotification) {
                itemView.set(BR.item, R.layout.notification_status_layout);
            }
        }
    };

    private View mRootView;

    public void setRootView(View view) {
        mRootView = view;
    }
}

Then I am binding the fragment to the VM

public class TimelineFragment extends Fragment {

    private TimelineVM mTimelineListVM;
    private TimelineListBinding mBinding;

    // newInstance constructor for creating fragment with arguments
    public static TimelineFragment newInstance() {
        TimelineFragment fragmentFirst = new TimelineFragment();
        return fragmentFirst;
    }

    // Store instance variables based on arguments passed
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
        mTimelineListVM = FslNotificationManager.getTimelineVM();
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mTimelineListVM.setRootView(getView());
    }

    // Inflate the view for the fragment based on layout XML
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mBinding = TimelineListBinding.inflate(inflater, container, false);

        mBinding.setTimelineVM(mTimelineListVM);
        mBinding.executePendingBindings();
        return mBinding.getRoot();
    }

    @Override
    public void onStart() {
        super.onStart();
    }
}

The layouts are each bound like this

    <data>

        <variable
            name="item"
            type="redacted.NotificationAbstract" />
    </data>

Then with that bound static list, I will do a
mTimelineVM.items.add(notification);

Recyclerview scroling to top when items changed.

Using a recyclerview with an ObservableList for the data. When items are added, the recyclerview scrolls back to the top. I suspect this is because the whole adapter is being incorrectly replaced. This happens in 1.0.0 but not 0.16

Unable to use binding collection adapter when header and footer is added to a list view

I am adding header and footer in a list view using ListView::addHeaderView and ListView::addFooterView
Getting exception :

java.lang.ClassCastException: android.widget.HeaderViewListAdapter cannot be cast to me.tatarka.bindingcollectionadapter.BindingListViewAdapter
    at me.tatarka.bindingcollectionadapter.BindingCollectionAdapters.setAdapter(BindingCollectionAdapters.java:27) ~[na:0.0]
    at to.go.databinding.ContentDrawerBinding.executeBindings(ContentDrawerBinding.java:142) ~[na:0.0]
    at android.databinding.ViewDataBinding.executePendingBindings(ViewDataBinding.java:355) ~[na:0.0]
    at android.databinding.ViewDataBinding$6.run(ViewDataBinding.java:172) ~[na:0.0]
    at android.databinding.ViewDataBinding$7.doFrame(ViewDataBinding.java:238) ~[na:0.0]
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:856) ~[na:0.0]
    at android.view.Choreographer.doCallbacks(Choreographer.java:670) ~[na:0.0]
    at android.view.Choreographer.doFrame(Choreographer.java:603) ~[na:0.0]
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844) ~[na:0.0]
    at android.os.Handler.handleCallback(Handler.java:739) ~[na:0.0]
    at android.os.Handler.dispatchMessage(Handler.java:95) ~[na:0.0]
    at android.os.Looper.loop(Looper.java:148) ~[na:0.0]
    at android.app.ActivityThread.main(ActivityThread.java:5417) ~[na:0.0]
    at java.lang.reflect.Method.invoke(Native Method) ~[na:0.0]
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) ~[na:0.0]
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) ~[na:0.0]

Basically it is failing here
BindingListViewAdapter adapter = (BindingListViewAdapter) adapterView.getAdapter();
as on adding header or footer the adapter changes to HeaderListViewAdapter

An easy fix for this I found is to replace BindingListViewAdapter adapter = (BindingListViewAdapter) adapterView.getAdapter(); with

Adapter listAdapter = adapterView.getAdapter();
BindingListViewAdapter<T> adapter;
if (listAdapter instanceof HeaderViewListAdapter) {
    adapter = (BindingListViewAdapter<T>) ((HeaderViewListAdapter) listAdapter)
        .getWrappedAdapter();
} else {
    adapter = (BindingListViewAdapter<T>) adapterView.getAdapter();
}

So i think this fix should be added in the library itself

Also i have a better way of adding header and footer view in listview

@BindingAdapter(value = {"app:footerView", "app:footerViewModel"}, requireAll = false)
public static void addFooterView(ListView listView, ItemView itemView, Object viewModel)
{
    ViewDataBinding footerView = DataBindingUtil
        .inflate(LayoutInflater.from(listView.getContext()), itemView.layoutRes(), null, false);
    if (itemView.bindingVariable() != ItemView.BINDING_VARIABLE_NONE) {
        footerView.setVariable(itemView.bindingVariable(), viewModel);
    }
    listView.addFooterView(footerView.getRoot());
}

@BindingAdapter(value = {"app:headerView", "app:headerViewModel"}, requireAll = false)
public static void addHeaderView(ListView listView, ItemView itemView, Object viewModel)
{
    ViewDataBinding headerView = DataBindingUtil
        .inflate(LayoutInflater.from(listView.getContext()), itemView.layoutRes(), null, false);
    if (itemView.bindingVariable() != ItemView.BINDING_VARIABLE_NONE) {
        headerView.setVariable(itemView.bindingVariable(), viewModel);
    }
    listView.addHeaderView(headerView.getRoot());
}

//in view model
public final ItemView footerItemView = ItemView.of(BR.viewModel, R.layout.footer_view);
public final ItemView headerItemView = ItemView.of(ItemView.BINDING_VARIABLE_NONE, R.layout.header_view);

Handling listeners on the list items

Hi,
thank you for your great library. It works fine, but I'm struggling with how to properly handle listeners on the Views that are inside the list item.

AFAIK it's possible to bind only one variable with the list item layout which contains data (using itemView.setBindingVariable()). That's not nice, because now I need to add listeners and their handling to the data object. I think it that listeners should be separated from data object. So I would ask for an advice or little refactoring which will allow to bind more variables to the list item view.

NoSuchMethodException

java.lang.RuntimeException: java.lang.NoSuchMethodException: [class me.tatarka.bindingcollectionadapter.ItemViewArg]
at me.tatarka.bindingcollectionadapter.Utils.createClass(Utils.java:107)
at me.tatarka.bindingcollectionadapter.BindingRecyclerViewAdapters$1.create(BindingRecyclerViewAdapters.java:44)
at me.tatarka.bindingcollectionadapter.BindingRecyclerViewAdapters.setAdapter(BindingRecyclerViewAdapters.java:27)
at com.paybay.quismart.databinding.FragmentGoogleplacesListBinding.executeBindings(FragmentGoogleplacesListBinding.java:135)
at android.databinding.ViewDataBinding.executePendingBindings(ViewDataBinding.java:348)
at android.databinding.ViewDataBinding$6.run(ViewDataBinding.java:165)
at android.databinding.ViewDataBinding$5.onViewAttachedToWindow(ViewDataBinding.java:135)
at android.view.View.dispatchAttachedToWindow(View.java:13552)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2689)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2696)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2696)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2696)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2696)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2696)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2696)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2696)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2696)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2696)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1299)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5891)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:550)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5294)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
Caused by: java.lang.NoSuchMethodException: [class me.tatarka.bindingcollectionadapter.ItemViewArg]
at java.lang.Class.getConstructor(Class.java:531)
at java.lang.Class.getConstructor(Class.java:495)
at me.tatarka.bindingcollectionadapter.Utils.createClass(Utils.java:105)
at me.tatarka.bindingcollectionadapter.BindingRecyclerViewAdapters$1.create(BindingRecyclerViewAdapters.java:44) 
at me.tatarka.bindingcollectionadapter.BindingRecyclerViewAdapters.setAdapter(BindingRecyclerViewAdapters.java:27) 
at com.paybay.quismart.databinding.FragmentGoogleplacesListBinding.executeBindings(FragmentGoogleplacesListBinding.java:135) 
at android.databinding.ViewDataBinding.executePendingBindings(ViewDataBinding.java:348) 
at android.databinding.ViewDataBinding$6.run(ViewDataBinding.java:165) 
at android.databinding.ViewDataBinding$5.onViewAttachedToWindow(ViewDataBinding.java:135) 
at android.view.View.dispatchAttachedToWindow(View.java:13552) 
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2689) 
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2696) 
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2696) 
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2696) 
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2696) 
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2696) 
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2696) 
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2696) 
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2696) 
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2696) 
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1299) 
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061) 
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5891) 
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767) 
at android.view.Choreographer.doCallbacks(Choreographer.java:580) 
at android.view.Choreographer.doFrame(Choreographer.java:550) 
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753) 
at android.os.Handler.handleCallback(Handler.java:739) 
at android.os.Handler.dispatchMessage(Handler.java:95) 
at android.os.Looper.loop(Looper.java:135) 
at android.app.ActivityThread.main(ActivityThread.java:5294) 
at java.lang.reflect.Method.invoke(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:372) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699) 

How to set default value for spinner?

I'm struggling with spinner. I have to select default item from the list but I couldn't find proper way to do it. I was also having problems with getting selected item from the list (in viewmodel) but I used view from onClick() to get it from view tree. It's working but again I'm not sure if that is recommended way to deal with. Can you provide some insight on that topic?

Edit: I tried using @BindingAdapter on Spinner to set selection but spinner's adapter is still null when method is executed.
Edit2: found a workaround for @BindingAdapter Spinner's null adapter by using notifyChange() on ViewModel in fragment's onResume(). Question remains if that's the simplest solution.

Weird behavior with onItemClick

Hello,

Here is the situation: I have a ListView configured with binding collection adapter. The items are filled in correctly. However, when I try to operate on the view returned by the onItemClick event, I observe strange behavior. Here is the code of the onItemClick method:

public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        boolean isSelected = //is this position selected already ?
        if(isSelected) {
            view.setBackgroundColor(Color.TRANSPARENT);
        } else {
            view.setBackgroundColor(ContextCompat.getColor(getActivity(), R.color.selected));
        }
    }

This method works absolutely fine when the list is short enough and you don't have to scroll down. But as soon as you start scrolling, other views than the ones clicked will be colored. Any idea on how to fix this issue ?

Thanks

Add support for itemview multi binding variable.

Hello, I am trying to use this library to bind something like the following
(Similar code can be found in the https://github.com/googlesamples/android-architecture/tree/todo-databinding
R.layout.task_item

<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="task"
            type="com.example.android.architecture.blueprints.todoapp.data.Task" />
        <variable
            name="actionHandler"
            type="com.example.android.architecture.blueprints.todoapp.tasks.TasksItemActionHandler" />
    </data>
   ...
</layout>

But it seems that itemview only accept single binding variable and I have no way to bind the TasksItemActionHandler in the adapter.
It will be great that itemview can accept multi binding variables. What do you think ? Thank you.

NullPointerException being thrown in BindingListViewAdapter.java

I have only been able to replicate this bug on an Android device version 4.1.2. The NullPointer happens on "itemView.layoutRes" in getItemViewType(). While debugging through the constructor, the ItemView parameter WAS null. The relevant part of the stacktrace has been posted below.

java.lang.NullPointerException
        at me.tatarka.bindingcollectionadapter.BindingListViewAdapter.getItemViewType(BindingListViewAdapter.java:192)
        at me.tatarka.bindingcollectionadapter.BindingListViewAdapter.getView(BindingListViewAdapter.java:144)
        at android.widget.AbsListView.obtainView(AbsListView.java:2340)
        at android.widget.ListView.onMeasure(ListView.java:1271)

If you have any insight as to why this is occurring, or if you require more information, please let me know.

Update: I have been able to replicate this on v4.0.4 and v4.2 devices as well.

notifyDataSetChanged not releasing old binding

When calling recyclerView adapter notifyDataSetChanged seems like the old bindings are not released. I noticed this when I put a breakpoint on executeBinding and its called multiple times even though I'm only updating 1 property.

I created a sample project for this https://github.com/xdgimf/SampleBindingCollectionAdapter

ItemViewModel

public class ItemViewModel {

    public final ObservableBoolean selected = new ObservableBoolean();

    public final ObservableField<String> text = new ObservableField<>();

    public final View.OnClickListener clickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (selected.get()) {
                selected.set(false);
            } else {
                selected.set(true);
            }
        }
    };

    public ItemViewModel(String text) {
        this.text.set(text);
    }

}
  1. Click on first item = call selected.set(true) then executeBinding is called once
  2. Click refresh = call recycler view adapter notifyDataSetChanged and first item is still selected
  3. Click first item again = call selected.set(false) then executeBinding is called twice

Also let say if you refresh 5 times, then executeBinding is called 5 times.

Update:
I found out that the problem was caused by using ObservableField, everytime the adapter creates a binding, ObservableField adds the binding to its callbacks, this callbacks is called everytime the property is changed.

Expanding Fragments

I am trying to data bind to a collection of elements where different typed elements can have a different fragment to represent them. To do this, I created a new BindngRecyclerViewAdapter but I am having the issue that when expand fragments during binding, they appear on top of one another. Here is my onBindBinding override

@Override
    public void onBindBinding(ViewDataBinding binding, int bindingVariable, @LayoutRes int layoutId, int position, T item) {
        super.onBindBinding(binding, bindingVariable, layoutId, position, item);

        Class fragmentClass = MainActivity.modelToFragment.get(item.getClass());
        if(fragmentClass != null) {
            try {
                Method ninst = fragmentClass.getMethod("newInstance", item.getClass());
                DialogFragment display = (DialogFragment)ninst.invoke(null, item);

                FragmentTransaction ft = ((AppCompatActivity)binding.getRoot().getContext()).getSupportFragmentManager().beginTransaction();
                ft.add(binding.getRoot().getId(), display);
                ft.commit();

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

When my app is running, I can see new cards being push into the view for each item in my ObservableArrayList, but the fragment is always expanded into the first card. Am I going about this wrong or is there some issue with the ViewDataBinding that I am being passed?

View pager refresh

In case of using ObservableArrayList<> as items in ViewPager, It is not respond for data change.

It could happen because in class BindingViewPagerAdapter. in method setItems
there is code:

        } else if (items != null) {
            this.items = new ObservableArrayList<>();
            this.items.addOnListChangedCallback(callback);
            this.items.addAll(items);
        } else {
            this.items = null;
        }

I think callback should be registered on source items.
Example:

else if (items != null) {
            items.addOnListChangedCallback(callback);
            this.items = new ObservableArrayList<>();
            this.items.addAll(items);
        } 

Allow adapter factories

Alow passing in an adapter factory to app:adapter instead of just a class name. This way you can avoid reflection and have more control over the constructor(s) if you want to.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.