Skip to content

Commit

Permalink
add KDelegateAdapter
Browse files Browse the repository at this point in the history
  • Loading branch information
dumchev committed Apr 27, 2018
1 parent 66f9b4a commit 32507a1
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 119 deletions.
169 changes: 90 additions & 79 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,119 @@
# DelegateAdapters
Simplify creating recycler view adapters with many different view types.
This lib is inspired by Hannes Dorfmann [AdapterDelegates](https://github.com/sockeqwe/AdapterDelegates).
If you are going to use it with Kotlin, go to the part [Example of usage in Kotlin](https://github.com/Liverm0r/DelegateAdapters/blob/master/README.md#example-of-usage-in-kotlin).

[Article](https://habr.com/post/341738/) about it on Russian.

## Dependencies

for java:
```groovy
compile 'com.github.liverm0r:delegateadapters:v1.11'
```

for kotlin:
```groovy
android {
//...
androidExtensions {
experimental = true
}
}
compile 'com.github.liverm0r:delegateadapters:v2.0'
```

You also have to add this in your project build.gradle

```groovy
allprojects {
repositories {
...
//...
maven { url 'https://jitpack.io' }
}
}
```

[![Build Status](https://travis-ci.org/sockeqwe/AdapterDelegates.svg?branch=master)](https://jitpack.io/#Liverm0r/delegateadapters)

## Example of usage in Kotlin

Write a model, which represents ui data:

```kotlin
class ImageViewModel(val title: String, @DrawableRes val imageRes: Int) : IComparableItem {

override fun id(): Any = title
override fun content(): Any = title + imageRes
}

```

ImageViewModel is just a POJO, implementing IComparableItem to be able to animate it out of the box with DiffUtils.

Write a delegate adapter:

```kotlin
class ImageDelegateAdapter(private val onImageClick: (ImageViewModel) -> Unit)
: KDelegateAdapter<ImageViewModel>() {

override fun onBind(item: ImageViewModel, viewHolder: KViewHolder)= with(viewHolder) {
tv_title.text = item.title
img_bg.setOnClickListener { onImageClick(item) }
img_bg.setImageResource(item.imageRes)
}

override fun isForViewType(items: List<*>, position: Int) = items[position] is ImageViewModel

override fun getLayoutId(): Int = R.layout.image_item
}

```

Check part `with(viewHolder)`. This works like basic view holder without creating one. Just override onBind and onCreate methods. See the [View holder pattern support and caching options](
https://github.com/Kotlin/KEEP/blob/master/proposals/android-extensions-entity-caching.md
) for more information.

To enable this magic, you need to turn on kotlin ext. experimental feature in your module build.gradle file:

```groovy
androidExtensions {
experimental = true
}
```

Now you can use DiffUtilCompositeAdapter just like the base RecyclerView.Adapter, composing it with whatever amount of delegate adapters:

```kotlin
adapter = DiffUtilCompositeAdapter.Builder()
.add(ImageDelegateAdapter(onImageClick))
.add(TextDelegateAdapter())
.add(CheckDelegateAdapter())
.build()
```

![example](https://github.com/Liverm0r/DelegateAdapters/blob/master/feed_example.jpg)

## Example of usage in Java

Write a Model:

```java
public class TextViewModel implements IComparableItem {

@NonNull public final String title;
@NonNull public final String description;

public TextViewModel(@NonNull String title, @NonNull String description) {
this.title = title;
this.description = description;
}

@Override public Object id() {return title;}
@Override public Object content() {return title + description;}
}

```

Inherit from BaseDelegateAdapter:

```java
Expand Down Expand Up @@ -72,26 +159,7 @@ public class TextDelegateAdapter extends

```

TextViewModel is just a POJO, implementing IComparableItem to be able to animate it out of the boxh by DiffUtils:

```java
public class TextViewModel implements IComparableItem {

@NonNull public final String title;
@NonNull public final String description;

public TextViewModel(@NonNull String title, @NonNull String description) {
this.title = title;
this.description = description;
}

@Override public Object id() {return title;}
@Override public Object content() {return title + description;}
}

```

Now you can use CompositeDelegateAdapter just like base RecyclerView.Adapter, composing it with whatever amount of delegate adapters:
And create your CompositeDelegateAdapter (RecyclerView.Adapter):

```java
adapter = new DiffUtilCompositeAdapter.Builder()
Expand All @@ -101,63 +169,6 @@ Now you can use CompositeDelegateAdapter just like base RecyclerView.Adapter, co
.build();
```

In current example you will just have three types - text, image, and checkbox

![example](https://github.com/Liverm0r/DelegateAdapters/blob/master/feed_example.jpg)

## Example of usage in Kotlin


With Kotlin delegate adapters become much smaller:

```kotlin

class ImageDelegateAdapter(private val onImageClick: (ImageViewModel) -> Unit)
: KDelegateAdapter<ImageViewModel>() {

override fun onBind(item: ImageViewModel, viewHolder: KViewHolder)= with(viewHolder) {
tv_title.text = item.title
img_bg.setOnClickListener { onImageClick(item) }
img_bg.setImageResource(item.imageRes)
}

override fun isForViewType(items: List<*>, position: Int) = items[position] is ImageViewModel

override fun getLayoutId(): Int = R.layout.image_item
}

```

Check part `wiht(viewHolder)`. This works like basic view holder without creating one. See the [View holder pattern support and caching options](
https://github.com/Kotlin/KEEP/blob/master/proposals/android-extensions-entity-caching.md
) for more information.

To enable this, you need to turn on kotlin ext. experimental feature in your module build.gradle file:

```groovy
androidExtensions {
experimental = true
}
```

After that you will be able to write some basic kotlin delegate adapter class, like

```kotlin
abstract class KDelegateAdapter<T> : BaseDelegateAdapter<KDelegateAdapter.KViewHolder, T>() {

abstract fun onBind(item: T, viewHolder: KViewHolder)

final override fun onBindViewHolder(view: View, item: T, viewHolder: KViewHolder) {
onBind(item, viewHolder)
}

override fun createViewHolder(parent: View): KViewHolder {
return KViewHolder(parent)
}

class KViewHolder(override val containerView: View?) : BaseViewHolder(containerView), LayoutContainer
}
```
Check the examples in this project.

## License
Expand Down
6 changes: 5 additions & 1 deletion delegateadapter/build.gradle
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-android'

group='com.github.Liverm0r'

android {
compileSdkVersion compileSdk


defaultConfig {
minSdkVersion minSdk
targetSdkVersion targetSdk
Expand All @@ -24,6 +25,9 @@ android {
}
}

androidExtensions {
experimental = true
}
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package com.example.dumchev.delegateadapters.base;

import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.delegateadapter.delegate.diff.IComparableItem;
import com.example.dumchev.delegateadapters.R;
import com.example.dumchev.delegateadapters.base.model.IViewModel;
import com.example.dumchev.delegateadapters.base.model.ImageViewModel;
import com.example.dumchev.delegateadapters.base.model.TextViewModel;

Expand All @@ -25,21 +26,22 @@ public class BadAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int TEXT_VIEW_TYPE = 1;
private static final int IMAGE_VIEW_TYPE = 2;

private List<IViewModel> items;
private List<IComparableItem> items;

public BadAdapter(List<IViewModel> items) {
public BadAdapter(List<IComparableItem> items) {
this.items = items;
}

public int getItemViewType(int position) {
IViewModel item = items.get(position);
IComparableItem item = items.get(position);
if (item instanceof TextViewModel) return TEXT_VIEW_TYPE;
if (item instanceof ImageViewModel) return IMAGE_VIEW_TYPE;
throw new IllegalArgumentException("Can't find view type for position " + position);
}

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
RecyclerView.ViewHolder holder;
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
if (viewType == TEXT_VIEW_TYPE) {
Expand All @@ -54,7 +56,7 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
if (viewType == TEXT_VIEW_TYPE) {
TextViewHolder txtViewHolder = (TextViewHolder) holder;
Expand All @@ -64,8 +66,8 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
} else if (viewType == IMAGE_VIEW_TYPE) {
ImageViewHolder imgViewHolder = (ImageViewHolder) holder;
ImageViewModel model = (ImageViewModel) items.get(position);
imgViewHolder.tvTitle.setText(model.title);
imgViewHolder.imageView.setImageResource(model.imageRes);
imgViewHolder.tvTitle.setText(model.getTitle());
imgViewHolder.imageView.setImageResource(model.getImageRes());
} else {
throw new IllegalArgumentException(
"Can't create bind holder fro position " + position);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.example.dumchev.delegateadapters.base.model

import android.support.annotation.DrawableRes

import com.example.delegateadapter.delegate.diff.IComparableItem

/**
* @author dumchev on 05.11.17.
*/
class ImageViewModel(val title: String, @DrawableRes val imageRes: Int) : IComparableItem {

override fun id(): Any = title
override fun content(): Any = title + imageRes
}

0 comments on commit 32507a1

Please sign in to comment.