Skip to content

Commit

Permalink
Merge pull request #2 from evant/master
Browse files Browse the repository at this point in the history
Update from source
  • Loading branch information
wongcain authored Aug 14, 2019
2 parents 98a3138 + 33c7a17 commit 0642119
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 88 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
### 3.1.0
- Bumped android gradle plugin verison to 3.4.1
- Fixed crashes caused by lifecycle owner usage

### 3.0.0
- Removed `LayoutManagers`. RecyclerView has support setting the LayoutManager in xml using it's
class name that doesn't rely on databinding.
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,26 @@ Easy way to bind collections to listviews and recyclerviews with the new [Androi

## Download

If you are using androidx use version `3.0.0`, this also uses databinding v2
If you are using androidx use version `3.1.0`, this also uses databinding v2

```groovy
compile 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter:3.0.0'
compile 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter-recyclerview:3.0.0'
implementation 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter:3.1.0'
implementation 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter-recyclerview:3.1.0'
```

otherwise, you can try out [databinding v2](https://developer.android.com/topic/libraries/data-binding/start#preview-compiler)
with version `2.3.0-beta3`

```groovy
compile 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter:2.3.0-beta3'
compile 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter-recyclerview:2.3.0-beta3'
implementation 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter:2.3.0-beta3'
implementation 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter-recyclerview:2.3.0-beta3'
```

or use the previous stable version

```groovy
compile 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter:2.2.0'
compile 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter-recyclerview:2.2.0'
implementation 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter:2.2.0'
implementation 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter-recyclerview:2.2.0'
```

## Usage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import androidx.databinding.ObservableList;
import androidx.databinding.OnRebindCallback;
import androidx.databinding.ViewDataBinding;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
Expand Down Expand Up @@ -108,10 +109,12 @@ public ViewDataBinding onCreateBinding(@NonNull LayoutInflater inflater, @Layout

@Override
public void onBindBinding(@NonNull ViewDataBinding binding, int variableId, @LayoutRes int layoutRes, int position, T item) {
boolean bound = itemBinding.bind(binding, item);
binding.setLifecycleOwner(lifecycleOwner);
if (bound) {
tryGetLifecycleOwner();
if (itemBinding.bind(binding, item)) {
binding.executePendingBindings();
if (lifecycleOwner != null) {
binding.setLifecycleOwner(lifecycleOwner);
}
}
}

Expand All @@ -122,9 +125,6 @@ public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
((ObservableList<T>) items).addOnListChangedCallback(callback);
}
this.recyclerView = recyclerView;
if (lifecycleOwner == null) {
lifecycleOwner = Utils.findLifecycleOwner(recyclerView);
}
}

@Override
Expand Down Expand Up @@ -250,6 +250,12 @@ public long getItemId(int position) {
return itemIds == null ? position : itemIds.getItemId(position, items.get(position));
}

private void tryGetLifecycleOwner() {
if (lifecycleOwner == null || lifecycleOwner.getLifecycle().getCurrentState() == Lifecycle.State.DESTROYED) {
lifecycleOwner = Utils.findLifecycleOwner(recyclerView);
}
}

private static class WeakReferenceOnListChangedCallback<T> extends ObservableList.OnListChangedCallback<ObservableList<T>> {
final WeakReference<BindingRecyclerViewAdapter<T>> adapterRef;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ObservableList;
import androidx.databinding.ViewDataBinding;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;

/**
Expand All @@ -35,7 +36,6 @@ public class BindingListViewAdapter<T> extends BaseAdapter implements BindingCol
private ItemIsEnabled<? super T> itemIsEnabled;
@Nullable
private LifecycleOwner lifecycleOwner;
private boolean failedToGetLifecycleOwner;

/**
* Constructs a new instance with the given item count.
Expand Down Expand Up @@ -106,10 +106,11 @@ public ViewDataBinding onCreateBinding(@NonNull LayoutInflater inflater, @Layout

@Override
public void onBindBinding(@NonNull ViewDataBinding binding, int variableId, @LayoutRes int layoutRes, int position, T item) {
boolean bound = itemBinding.bind(binding, item);
binding.setLifecycleOwner(lifecycleOwner);
if (bound) {
if (itemBinding.bind(binding, item)) {
binding.executePendingBindings();
if (lifecycleOwner != null) {
binding.setLifecycleOwner(lifecycleOwner);
}
}
}

Expand Down Expand Up @@ -203,12 +204,9 @@ public final View getDropDownView(int position, @Nullable View convertView, @Non
}
}

private void tryGetLifecycleOwner(ViewGroup parent) {
if (!failedToGetLifecycleOwner && lifecycleOwner == null) {
lifecycleOwner = Utils.findLifecycleOwner(parent);
if (lifecycleOwner == null) {
failedToGetLifecycleOwner = true;
}
private void tryGetLifecycleOwner(View view) {
if (lifecycleOwner == null || lifecycleOwner.getLifecycle().getCurrentState() == Lifecycle.State.DESTROYED) {
lifecycleOwner = Utils.findLifecycleOwner(view);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ObservableList;
import androidx.databinding.ViewDataBinding;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.viewpager.widget.PagerAdapter;

Expand All @@ -31,7 +32,6 @@ public class BindingViewPagerAdapter<T> extends PagerAdapter implements BindingC
private PageTitles<T> pageTitles;
@Nullable
private LifecycleOwner lifecycleOwner;
private boolean failedToGetLifecycleOwner;
private List<View> views = new ArrayList<>();

@Override
Expand Down Expand Up @@ -93,11 +93,11 @@ public ViewDataBinding onCreateBinding(@NonNull LayoutInflater inflater, @Layout

@Override
public void onBindBinding(@NonNull ViewDataBinding binding, int variableId, @LayoutRes int layoutRes, int position, T item) {
boolean bound = itemBinding.bind(binding, item);
binding.setLifecycleOwner(lifecycleOwner);
if (bound) {
if (itemBinding.bind(binding, item)) {
binding.executePendingBindings();
binding.setLifecycleOwner(lifecycleOwner);
if (lifecycleOwner != null) {
binding.setLifecycleOwner(lifecycleOwner);
}
}
}

Expand Down Expand Up @@ -142,12 +142,9 @@ public Object instantiateItem(@NonNull ViewGroup container, int position) {
return view;
}

private void tryGetLifecycleOwner(ViewGroup parent) {
if (!failedToGetLifecycleOwner && lifecycleOwner == null) {
lifecycleOwner = Utils.findLifecycleOwner(parent);
if (lifecycleOwner == null) {
failedToGetLifecycleOwner = true;
}
private void tryGetLifecycleOwner(View view) {
if (lifecycleOwner == null || lifecycleOwner.getLifecycle().getCurrentState() == Lifecycle.State.DESTROYED) {
lifecycleOwner = Utils.findLifecycleOwner(view);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import androidx.annotation.MainThread;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.Observable;
import androidx.databinding.OnRebindCallback;
import androidx.databinding.ViewDataBinding;

import android.os.Looper;
Expand All @@ -16,21 +14,13 @@
import androidx.annotation.LayoutRes;
import androidx.lifecycle.LifecycleOwner;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
* Helper databinding utilities. May be made public some time in the future if they prove to be
* useful.
*/
class Utils {
private static final String TAG = "BCAdapters";

@Nullable
private static Field lifecycleOwnerField;
private static boolean fieldFaild;

/**
* Helper to throw an exception when {@link androidx.databinding.ViewDataBinding#setVariable(int,
* Object)} returns false.
Expand All @@ -44,43 +34,22 @@ static void throwMissingVariable(ViewDataBinding binding, int bindingVariable, @
}

/**
* Returns the lifecycle owner associated with the given view. This currently requires the view
* to use databinding and uses reflection. This will hopefully be replaced with a better
* implementation once https://issuetracker.google.com/issues/112929938 gets implemented.
* 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);
if (binding == null) {
return null;
LifecycleOwner lifecycleOwner = null;
if (binding != null) {
lifecycleOwner = binding.getLifecycleOwner();
}
return getLifecycleOwner(binding);
}

/**
* Returns the lifecycle owner from a {@code ViewDataBinding} using reflection.
*/
@Nullable
@MainThread
private static LifecycleOwner getLifecycleOwner(ViewDataBinding binding) {
if (!fieldFaild && lifecycleOwnerField == null) {
try {
lifecycleOwnerField = ViewDataBinding.class.getDeclaredField("mLifecycleOwner");
lifecycleOwnerField.setAccessible(true);
} catch (NoSuchFieldException e) {
fieldFaild = true;
return null;
}
}
if (lifecycleOwnerField == null) {
return null;
}
try {
return (LifecycleOwner) lifecycleOwnerField.get(binding);
} catch (IllegalAccessException e) {
return null;
Context ctx = view.getContext();
if (lifecycleOwner == null && ctx instanceof LifecycleOwner) {
lifecycleOwner = (LifecycleOwner) ctx;
}
return lifecycleOwner;
}

/**
Expand All @@ -93,15 +62,4 @@ static void ensureChangeOnMainThread() {
}
}

/**
* Constructs a binding adapter class from it's class name using reflection.
*/
@SuppressWarnings("unchecked")
static <T, A extends BindingCollectionAdapter<T>> A createClass(Class<? extends BindingCollectionAdapter> adapterClass, ItemBinding<T> itemBinding) {
try {
return (A) adapterClass.getConstructor(ItemBinding.class).newInstance(itemBinding);
} catch (Exception e1) {
throw new RuntimeException(e1);
}
}
}
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
ext.kotlin_version = '1.3.0'
ext.agp_version = '3.3.0'
ext.kotlin_version = '1.3.31'
ext.agp_version = '3.4.1'
repositories {
google()
jcenter()
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# org.gradle.parallel=true

group=me.tatarka.bindingcollectionadapter2
version=3.0.0
version=3.1.1-SNAPSHOT
android.databinding.enableV2=true
android.useAndroidX=true
android.enableJetifier=true

0 comments on commit 0642119

Please sign in to comment.