diff --git a/README.md b/README.md index 2236f8f..0e166aa 100644 --- a/README.md +++ b/README.md @@ -379,13 +379,6 @@ If you attempt to retrieve an adapter from a view right after binding it you may 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](https://issuetracker.google.com/issues/112929938) gets resolved. - ## License Copyright 2015 Evan Tatarka diff --git a/app/build.gradle b/app/build.gradle index e1d5a66..79e0edc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -30,6 +30,9 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + kotlinOptions { + jvmTarget = "1.8" + } dataBinding { enabled = true } @@ -42,15 +45,17 @@ dependencies { implementation project(':bindingcollectionadapter-viewpager2') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'androidx.activity:activity:1.2.0-alpha03' + implementation 'androidx.fragment:fragment:1.3.0-alpha03' implementation 'androidx.appcompat:appcompat:1.1.0' - implementation 'com.google.android.material:material:1.2.0-alpha01' + implementation 'com.google.android.material:material:1.2.0-alpha05' implementation 'androidx.legacy:legacy-support-v4:1.0.0' - implementation 'androidx.recyclerview:recyclerview:1.0.0' - implementation 'androidx.vectordrawable:vectordrawable-animated:1.0.0' - implementation 'androidx.lifecycle:lifecycle-runtime:2.0.0' - implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0' - implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.0.0' - implementation 'androidx.paging:paging-runtime:2.0.0' + implementation 'androidx.recyclerview:recyclerview:1.1.0' + implementation 'androidx.vectordrawable:vectordrawable-animated:1.1.0' + implementation 'androidx.lifecycle:lifecycle-runtime:2.2.0' + implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' + implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0' + implementation 'androidx.paging:paging-runtime:2.1.2' kapt "com.android.databinding:compiler:$agp_version" } diff --git a/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentDiffRecyclerView.kt b/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentDiffRecyclerView.kt index d71be14..f00a6f5 100644 --- a/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentDiffRecyclerView.kt +++ b/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentDiffRecyclerView.kt @@ -23,7 +23,7 @@ class FragmentDiffRecyclerView : Fragment() { savedInstanceState: Bundle? ): View? { return DiffRecyclerViewBinding.inflate(inflater, container, false).also { - it.setLifecycleOwner(this) + it.lifecycleOwner = this it.viewModel = viewModel it.listeners = viewModel it.executePendingBindings() diff --git a/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentListView.kt b/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentListView.kt index e47b86f..762357b 100644 --- a/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentListView.kt +++ b/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentListView.kt @@ -24,7 +24,7 @@ class FragmentListView : Fragment() { savedInstanceState: Bundle? ): View? { return ListViewBinding.inflate(inflater, container, false).also { - it.setLifecycleOwner(this) + it.lifecycleOwner = this it.viewModel = viewModel it.listeners = viewModel it.executePendingBindings() diff --git a/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentPagedRecyclerView.kt b/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentPagedRecyclerView.kt index e271e6e..88edc91 100644 --- a/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentPagedRecyclerView.kt +++ b/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentPagedRecyclerView.kt @@ -23,7 +23,7 @@ class FragmentPagedRecyclerView : Fragment() { savedInstanceState: Bundle? ): View? { return PagedRecyclerViewBinding.inflate(inflater, container, false).also { - it.setLifecycleOwner(this) + it.lifecycleOwner = this it.viewModel = viewModel it.listeners = viewModel it.executePendingBindings() diff --git a/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentRecyclerView.kt b/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentRecyclerView.kt index f847baa..b9e641f 100644 --- a/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentRecyclerView.kt +++ b/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentRecyclerView.kt @@ -24,7 +24,7 @@ class FragmentRecyclerView : Fragment() { savedInstanceState: Bundle? ): View? { return RecyclerViewBinding.inflate(inflater, container, false).also { - it.setLifecycleOwner(this) + it.lifecycleOwner = this it.viewModel = viewModel it.listeners = viewModel it.executePendingBindings() diff --git a/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentSpinnerView.kt b/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentSpinnerView.kt index 99eaa70..fb0a1c1 100644 --- a/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentSpinnerView.kt +++ b/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentSpinnerView.kt @@ -25,7 +25,7 @@ class FragmentSpinnerView : Fragment() { savedInstanceState: Bundle? ): View? { return SpinnerViewBinding.inflate(inflater, container, false).also { - it.setLifecycleOwner(this) + it.lifecycleOwner = this it.viewModel = viewModel it.listeners = viewModel it.executePendingBindings() diff --git a/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentViewPager2View.kt b/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentViewPager2View.kt index 153345d..8e4aa4b 100644 --- a/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentViewPager2View.kt +++ b/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentViewPager2View.kt @@ -27,7 +27,7 @@ class FragmentViewPager2View : Fragment() { savedInstanceState: Bundle? ): View? { return Viewpager2ViewBinding.inflate(inflater, container, false).also { - it.setLifecycleOwner(this) + it.lifecycleOwner = this it.viewModel = viewModel it.listeners = PagerListeners(viewModel) it.executePendingBindings() diff --git a/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentViewPagerView.kt b/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentViewPagerView.kt index 97868cd..cb5de2e 100644 --- a/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentViewPagerView.kt +++ b/app/src/main/java/me/tatarka/bindingcollectionadapter/sample/FragmentViewPagerView.kt @@ -25,7 +25,7 @@ class FragmentViewPagerView : Fragment() { savedInstanceState: Bundle? ): View? { return ViewpagerViewBinding.inflate(inflater, container, false).also { - it.setLifecycleOwner(this) + it.lifecycleOwner = this it.viewModel = viewModel it.listeners = PagerListeners(it, viewModel) it.executePendingBindings() diff --git a/bindingcollectionadapter-paging/build.gradle b/bindingcollectionadapter-paging/build.gradle index 49c80dd..2a1f76a 100644 --- a/bindingcollectionadapter-paging/build.gradle +++ b/bindingcollectionadapter-paging/build.gradle @@ -38,9 +38,9 @@ dependencies { testImplementation 'org.assertj:assertj-core:3.6.2' testImplementation 'org.mockito:mockito-core:2.19.0' - androidTestImplementation 'androidx.test:runner:1.1.0' - androidTestImplementation 'androidx.test:rules:1.1.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' + androidTestImplementation 'androidx.test:runner:1.2.0' + androidTestImplementation 'androidx.test:rules:1.2.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' androidTestImplementation 'com.squareup.assertj:assertj-android:1.1.0' androidTestImplementation 'androidx.core:core:1.0.0' } diff --git a/bindingcollectionadapter-recyclerview/build.gradle b/bindingcollectionadapter-recyclerview/build.gradle index c80b6d9..34e7af4 100644 --- a/bindingcollectionadapter-recyclerview/build.gradle +++ b/bindingcollectionadapter-recyclerview/build.gradle @@ -37,9 +37,9 @@ dependencies { testImplementation 'org.assertj:assertj-core:3.6.2' testImplementation 'org.mockito:mockito-core:2.19.0' - androidTestImplementation 'androidx.test:runner:1.1.0' - androidTestImplementation 'androidx.test:rules:1.1.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' + androidTestImplementation 'androidx.test:runner:1.2.0' + androidTestImplementation 'androidx.test:rules:1.2.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' androidTestImplementation 'com.squareup.assertj:assertj-android:1.1.0' androidTestImplementation 'androidx.core:core:1.0.0' } diff --git a/bindingcollectionadapter-recyclerview/src/main/java/me/tatarka/bindingcollectionadapter2/BindingRecyclerViewAdapter.java b/bindingcollectionadapter-recyclerview/src/main/java/me/tatarka/bindingcollectionadapter2/BindingRecyclerViewAdapter.java index c3a78a7..8edc835 100644 --- a/bindingcollectionadapter-recyclerview/src/main/java/me/tatarka/bindingcollectionadapter2/BindingRecyclerViewAdapter.java +++ b/bindingcollectionadapter-recyclerview/src/main/java/me/tatarka/bindingcollectionadapter2/BindingRecyclerViewAdapter.java @@ -18,6 +18,7 @@ import androidx.databinding.ViewDataBinding; import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.ViewTreeLifecycleOwner; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView.ViewHolder; @@ -62,18 +63,11 @@ public void setItemBinding(@NonNull ItemBinding itemBinding) { * Sets the lifecycle owner of this adapter to work with {@link androidx.lifecycle.LiveData}. * This is normally not necessary, but due to an androidx limitation, you need to set this if * the containing view is not using databinding. + * + * @deprecated This is no longer needed. Calling it is a no-op. */ + @Deprecated public void setLifecycleOwner(@Nullable LifecycleOwner lifecycleOwner) { - this.lifecycleOwner = lifecycleOwner; - if (recyclerView != null) { - for (int i = 0; i < recyclerView.getChildCount(); i++) { - View child = recyclerView.getChildAt(i); - ViewDataBinding binding = DataBindingUtil.getBinding(child); - if (binding != null) { - binding.setLifecycleOwner(lifecycleOwner); - } - } - } } @NonNull @@ -266,7 +260,7 @@ public long getItemId(int position) { private void tryGetLifecycleOwner() { if (lifecycleOwner == null || lifecycleOwner.getLifecycle().getCurrentState() == Lifecycle.State.DESTROYED) { - lifecycleOwner = Utils.findLifecycleOwner(recyclerView); + lifecycleOwner = ViewTreeLifecycleOwner.get(recyclerView); } } diff --git a/bindingcollectionadapter-viewpager2/build.gradle b/bindingcollectionadapter-viewpager2/build.gradle index a7a0834..8eaf286 100644 --- a/bindingcollectionadapter-viewpager2/build.gradle +++ b/bindingcollectionadapter-viewpager2/build.gradle @@ -38,9 +38,9 @@ dependencies { testImplementation 'org.assertj:assertj-core:3.6.2' testImplementation 'org.mockito:mockito-core:2.19.0' - androidTestImplementation 'androidx.test:runner:1.1.0' - androidTestImplementation 'androidx.test:rules:1.1.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' + androidTestImplementation 'androidx.test:runner:1.2.0' + androidTestImplementation 'androidx.test:rules:1.2.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' androidTestImplementation 'com.squareup.assertj:assertj-android:1.1.0' androidTestImplementation 'androidx.core:core:1.0.0' } diff --git a/bindingcollectionadapter/build.gradle b/bindingcollectionadapter/build.gradle index 38efba6..3007dcc 100644 --- a/bindingcollectionadapter/build.gradle +++ b/bindingcollectionadapter/build.gradle @@ -31,15 +31,16 @@ android { dependencies { implementation 'androidx.core:core:1.0.0' + implementation "androidx.lifecycle:lifecycle-runtime:2.3.0-alpha01" implementation 'androidx.legacy:legacy-support-core-ui:1.0.0' testImplementation 'junit:junit:4.12' testImplementation 'org.assertj:assertj-core:3.6.2' testImplementation 'org.mockito:mockito-core:2.19.0' - androidTestImplementation 'androidx.test:runner:1.1.0' - androidTestImplementation 'androidx.test:rules:1.1.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' + androidTestImplementation 'androidx.test:runner:1.2.0' + androidTestImplementation 'androidx.test:rules:1.2.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' androidTestImplementation 'com.squareup.assertj:assertj-android:1.1.0' } diff --git a/bindingcollectionadapter/src/main/java/me/tatarka/bindingcollectionadapter2/BindingListViewAdapter.java b/bindingcollectionadapter/src/main/java/me/tatarka/bindingcollectionadapter2/BindingListViewAdapter.java index 60535ed..23e2ff3 100644 --- a/bindingcollectionadapter/src/main/java/me/tatarka/bindingcollectionadapter2/BindingListViewAdapter.java +++ b/bindingcollectionadapter/src/main/java/me/tatarka/bindingcollectionadapter2/BindingListViewAdapter.java @@ -16,6 +16,7 @@ import androidx.databinding.ViewDataBinding; import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.ViewTreeLifecycleOwner; /** * A {@link BaseAdapter} that binds items to layouts using the given {@link ItemBinding} If you give @@ -61,10 +62,11 @@ public void setItemBinding(@NonNull ItemBinding itemBinding) { * Sets the lifecycle owner of this adapter to work with {@link androidx.lifecycle.LiveData}. * This is normally not necessary, but due to an androidx limitation, you need to set this if * the containing view is not using databinding. + * + * @deprecated No longer needed. Calling is a no-op. */ + @Deprecated public void setLifecycleOwner(@Nullable LifecycleOwner lifecycleOwner) { - this.lifecycleOwner = lifecycleOwner; - notifyDataSetChanged(); } @NonNull @@ -214,7 +216,7 @@ public final View getDropDownView(int position, @Nullable View convertView, @Non private void tryGetLifecycleOwner(View view) { if (lifecycleOwner == null || lifecycleOwner.getLifecycle().getCurrentState() == Lifecycle.State.DESTROYED) { - lifecycleOwner = Utils.findLifecycleOwner(view); + lifecycleOwner = ViewTreeLifecycleOwner.get(view); } } diff --git a/bindingcollectionadapter/src/main/java/me/tatarka/bindingcollectionadapter2/BindingViewPagerAdapter.java b/bindingcollectionadapter/src/main/java/me/tatarka/bindingcollectionadapter2/BindingViewPagerAdapter.java index e8ed55a..ef425f9 100644 --- a/bindingcollectionadapter/src/main/java/me/tatarka/bindingcollectionadapter2/BindingViewPagerAdapter.java +++ b/bindingcollectionadapter/src/main/java/me/tatarka/bindingcollectionadapter2/BindingViewPagerAdapter.java @@ -16,6 +16,7 @@ import androidx.databinding.ViewDataBinding; import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.ViewTreeLifecycleOwner; import androidx.viewpager.widget.PagerAdapter; /** @@ -53,15 +54,11 @@ public void setItemBinding(@NonNull ItemBinding itemBinding) { * Sets the lifecycle owner of this adapter to work with {@link androidx.lifecycle.LiveData}. * This is normally not necessary, but due to an androidx limitation, you need to set this if * the containing view is not using databinding. + * + * @deprecated No longer needs to be called. Is a no-op */ + @Deprecated public void setLifecycleOwner(@Nullable LifecycleOwner lifecycleOwner) { - this.lifecycleOwner = lifecycleOwner; - for (View view : views) { - ViewDataBinding binding = DataBindingUtil.getBinding(view); - if (binding != null) { - binding.setLifecycleOwner(lifecycleOwner); - } - } } @NonNull @@ -105,9 +102,6 @@ public ViewDataBinding onCreateBinding(@NonNull LayoutInflater inflater, @Layout public void onBindBinding(@NonNull ViewDataBinding binding, int variableId, @LayoutRes int layoutRes, int position, T item) { if (itemBinding.bind(binding, item)) { binding.executePendingBindings(); - if (lifecycleOwner != null) { - binding.setLifecycleOwner(lifecycleOwner); - } } } @@ -154,7 +148,7 @@ public Object instantiateItem(@NonNull ViewGroup container, int position) { private void tryGetLifecycleOwner(View view) { if (lifecycleOwner == null || lifecycleOwner.getLifecycle().getCurrentState() == Lifecycle.State.DESTROYED) { - lifecycleOwner = Utils.findLifecycleOwner(view); + lifecycleOwner = ViewTreeLifecycleOwner.get(view); } } diff --git a/bindingcollectionadapter/src/main/java/me/tatarka/bindingcollectionadapter2/Utils.java b/bindingcollectionadapter/src/main/java/me/tatarka/bindingcollectionadapter2/Utils.java index 6d650ee..cc7ef86 100644 --- a/bindingcollectionadapter/src/main/java/me/tatarka/bindingcollectionadapter2/Utils.java +++ b/bindingcollectionadapter/src/main/java/me/tatarka/bindingcollectionadapter2/Utils.java @@ -2,17 +2,11 @@ import android.content.Context; import android.content.res.Resources; - -import androidx.annotation.MainThread; -import androidx.annotation.Nullable; -import androidx.databinding.DataBindingUtil; -import androidx.databinding.ViewDataBinding; - import android.os.Looper; -import android.view.View; import androidx.annotation.LayoutRes; -import androidx.lifecycle.LifecycleOwner; +import androidx.databinding.DataBindingUtil; +import androidx.databinding.ViewDataBinding; /** * Helper databinding utilities. May be made public some time in the future if they prove to be @@ -33,25 +27,6 @@ static void throwMissingVariable(ViewDataBinding binding, int bindingVariable, @ throw new IllegalStateException("Could not bind variable '" + bindingVariableName + "' in layout '" + layoutName + "'"); } - /** - * Returns the lifecycle owner associated with the given view. Tries to get lifecycle owner first - * from ViewDataBinding, else from View Context if view is not data-bound. - */ - @Nullable - @MainThread - static LifecycleOwner findLifecycleOwner(View view) { - ViewDataBinding binding = DataBindingUtil.findBinding(view); - LifecycleOwner lifecycleOwner = null; - if (binding != null) { - lifecycleOwner = binding.getLifecycleOwner(); - } - Context ctx = view.getContext(); - if (lifecycleOwner == null && ctx instanceof LifecycleOwner) { - lifecycleOwner = (LifecycleOwner) ctx; - } - return lifecycleOwner; - } - /** * Ensures the call was made on the main thread. This is enforced for all ObservableList change * operations. diff --git a/gradle.properties b/gradle.properties index 769e363..3712c9a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,6 +18,6 @@ # org.gradle.parallel=true group=me.tatarka.bindingcollectionadapter2 -version=4.0.0 +version=4.1.0-SNAPSHOT android.useAndroidX=true android.enableJetifier=true \ No newline at end of file