Skip to content

Commit

Permalink
Merge pull request #3 from trevjonez/dagger_split_lib
Browse files Browse the repository at this point in the history
Lazy delegates, and all in on dagger.
  • Loading branch information
trevjonez authored Apr 8, 2019
2 parents 953d6d3 + 55640cb commit 5a5c514
Show file tree
Hide file tree
Showing 53 changed files with 1,023 additions and 506 deletions.
7 changes: 7 additions & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
## Changelog

### 0.6.0 - BREAKING CHANGES
- Module breakup and artifact id changes
- Move adapter configuration entirely into constructor
- Remove androidx list differ provider impl's. Threading is on the consumer now.

### 0.5.0
- Optional RxAndroid Dependency to provide an impl of an RX based diff processing list provider
- Rename the existing providers, not everything needs to be poly. Breaking Change, Migration provided via deprecation.
Expand Down
102 changes: 71 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,12 @@ A composable recycler view adapter.

## Installation

Available via [jcenter](https://bintray.com/trevorjones141/maven/PolyAdapter-Android) or [jitpack.io](https://jitpack.io/#trevjonez/polyadapter-android):
Available via [jcenter](https://bintray.com/trevorjones141/maven/PolyAdapter-Android)

from jcenter:
```groovy
implementation 'com.trevjonez.polyadapter:core:0.5.0'
```

from jitpack:
```groovy
implementation 'com.github.trevjonez.polyadapter-android:core:0.5.0'
implementation 'com.trevjonez.polyadapter:core:$polyAdapterVersion'
implementation 'com.trevjonez.polyadapter:provider-rxjava2:$polyAdapterVersion'
```

## Usage
Expand All @@ -26,34 +22,87 @@ To use the library are three core types you need to be aware of.
1. `PolyAdapter.ItemProvider`
2. `PolyAdapter.BindingDelegate`

In order to create a `PolyAdapter` you need to provide the constructor with a `PolyAdapter.ItemProvider` implementation.
You can use one of the provided ItemProvider implementations or create your own.
The recommended way to consume `PolyAdapter` is via [dagger.](https://google.github.io/dagger/)

`AsyncListProvider` operates on `List<Any>`:
Provide a binding for `ItemProvider` and utilize map multi-bindings for `Delegates`:
```kotlin
val adapter = PolyAdapter(AsyncListProvider())
@Module(includes = [
DelegatesModule::class,
ProviderModule::class
])
abstract class PolyAdapterConfigModule

@Module
abstract class DelegatesModule {
@Binds
@IntoMap
@ClassKey(CategoryTitle::class)
abstract fun categoryDelegate(impl: CategoryDelegate):
PolyAdapter.BindingDelegate<*, *>

@Binds
@IntoMap
@ClassKey(DividerLine::class)
abstract fun dividerDelegate(impl: DividerDelegate):
PolyAdapter.BindingDelegate<*, *>

@Binds
@IntoMap
@ClassKey(Movie::class)
abstract fun movieDelegate(impl: MovieDelegate):
PolyAdapter.BindingDelegate<*, *>

@Binds
abstract fun listProvider(impl: RxListProvider):
PolyAdapter.ItemProvider
}

@Module
class ProviderModule {
@Provides
@ActivityScope
fun rxProvider() = RxListProvider()
}
```

Then you can add your `PolyAdapter.BindingDelegate` implementations to your new adapter:
Request an injection of a `PolyAdapter` instance and pass it to your recycler:
```kotlin
val polyAdapter = PolyAdapter(AsyncListProvider()).apply {
addDelegate(FooDelegate())
addDelegate(BarDelegate())
}

@Inject lateinit var polyAdapter: PolyAdapter

[...]

recyclerView.apply {
adapter = polyAdapter
}

```

After that your adapter is ready to serve items via the ItemProvider we injected it with.
This can be done either directly through the item provider's concrete api or one of the
extension methods provided in the main library to make it feel a bit more familiar.
To update the list contents send updates via the `ItemProvider` implementation.
`RxListProvider`:
```kotlin
@Inject lateinit var itemProvider: RxListProvider

[...]

someLiveDataSource
.compose(itemProvider)
.subscribe { applyNewData ->
applyNewData()
}
```

`ListProvider`:
```kotlin
someLiveDataSource.subscribe { listItems ->
adapter.updateList(listItems)
}
@Inject lateinit var itemProvider: ListProvider

[...]

val diffWork = itemProvider.updateItems(newItems)

val applyNewData = diffWork() //do this from background thread

applyNewData() //do this on main thread
```

#### Binding Delegate's
Expand Down Expand Up @@ -142,15 +191,6 @@ method that includes payloads that are returned from your `DiffUtil.ItemCallback

`PolyAdapter.OnViewDetachedDelegate` - Adds `onDetach`

#### RxListProvider

An RxJava based `RxListProvider` is also available. You can compose it
on an observable of your source data and will transform your data into
a ready to use function. Call the resulting function from the
main thread to apply the diff and swap the data set, this also eliminates
the need for a content changed callback as seen in `AsyncListProvider`.
The transforming nature also keep disposal management simple.

## License

Copyright 2018 Trevor Jones
Expand Down
34 changes: 26 additions & 8 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.trevjonez.polyadapter"
applicationId "polyadapter.sample"
minSdkVersion 21
targetSdkVersion 28
versionCode 1
Expand All @@ -21,18 +21,36 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
testOptions {
unitTests {
includeAndroidResources = true
}
}
}

dependencies {
implementation(project(":core"))
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version")
implementation(project(":provider-rxjava2"))
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion")
implementation("androidx.appcompat:appcompat:1.0.0")
implementation('androidx.constraintlayout:constraintlayout:1.1.3')
implementation("androidx.constraintlayout:constraintlayout:1.1.3")
implementation("io.reactivex.rxjava2:rxkotlin:2.3.0")

kapt('com.github.bumptech.glide:compiler:4.9.0')
implementation('com.github.bumptech.glide:glide:4.9.0')

kapt("androidx.databinding:databinding-compiler:$agpVersion")

kapt('com.github.bumptech.glide:compiler:4.8.0')
implementation('com.github.bumptech.glide:glide:4.8.0')
implementation("com.google.dagger:dagger:$daggerVersion")
kapt("com.google.dagger:dagger-compiler:$daggerVersion")

kapt("androidx.databinding:databinding-compiler:$agp_version")
implementation("com.google.dagger:dagger-android:$daggerVersion")
implementation("com.google.dagger:dagger-android-support:$daggerVersion")
kapt("com.google.dagger:dagger-android-processor:$daggerVersion")

testImplementation('junit:junit:4.12')
testImplementation("androidx.test:runner:1.1.0")
testImplementation("androidx.test.ext:junit:1.1.0")
testImplementation("org.robolectric:robolectric:4.2.1")
testImplementation("androidx.test.espresso:espresso-core:3.1.0")
testImplementation("androidx.test.espresso:espresso-intents:3.1.0")
testImplementation("androidx.test.espresso:espresso-idling-resource:3.1.0")
}
9 changes: 7 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.trevjonez.polyadapter">
package="polyadapter.sample">

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

<application
android:name=".App"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">

<uses-library android:name="android.test.runner"
android:required="false" />

<activity
android:name=".sample.SampleActivity"
android:name=".SampleActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
Expand Down

This file was deleted.

6 changes: 6 additions & 0 deletions app/src/main/java/polyadapter/sample/ActivityScope.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package polyadapter.sample

import javax.inject.Scope

@Scope
annotation class ActivityScope
10 changes: 10 additions & 0 deletions app/src/main/java/polyadapter/sample/App.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package polyadapter.sample

import dagger.android.AndroidInjector
import dagger.android.support.DaggerApplication

class App: DaggerApplication() {
override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
return DaggerAppComponent.create()
}
}
15 changes: 15 additions & 0 deletions app/src/main/java/polyadapter/sample/AppComponent.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package polyadapter.sample

import dagger.Component
import dagger.android.AndroidInjectionModule
import dagger.android.AndroidInjector
import javax.inject.Singleton

@Singleton
@Component(
modules = [
SampleActivity.BindingModule::class,
AndroidInjectionModule::class
]
)
interface AppComponent : AndroidInjector<App>
Original file line number Diff line number Diff line change
@@ -1,40 +1,17 @@
package com.trevjonez.polyadapter.sample
package polyadapter.sample

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.LinearLayoutManager
import com.trevjonez.polyadapter.PolyAdapter
import com.trevjonez.polyadapter.R
import com.trevjonez.polyadapter.databinding.SampleActivityBinding
import com.trevjonez.polyadapter.providers.AsyncListProvider
import com.trevjonez.polyadapter.providers.updateList
import com.trevjonez.polyadapter.sample.data.CategoryTitle
import com.trevjonez.polyadapter.sample.data.DividerLine
import com.trevjonez.polyadapter.sample.data.Movie
import com.trevjonez.polyadapter.sample.delegates.CategoryDelegate
import com.trevjonez.polyadapter.sample.delegates.DividerDelegate
import com.trevjonez.polyadapter.sample.delegates.MovieDelegate
import io.reactivex.Observable
import polyadapter.sample.data.CategoryTitle
import polyadapter.sample.data.DividerLine
import polyadapter.sample.data.Movie
import javax.inject.Inject

class SampleActivity : AppCompatActivity() {

private lateinit var viewBinding: SampleActivityBinding
private val polyAdapter = PolyAdapter(AsyncListProvider()).apply {
addDelegate(CategoryDelegate())
addDelegate(DividerDelegate())
addDelegate(MovieDelegate())
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewBinding = DataBindingUtil.setContentView(this, R.layout.sample_activity)

viewBinding.recycler.apply {
layoutManager = LinearLayoutManager(context)
adapter = polyAdapter
}

polyAdapter.updateList(listOf(
/**
* place holder for VM/Presenter/etc...
*/
class ArchitecturalThing @Inject constructor() {
fun dataSource(): Observable<List<Any>> {
return Observable.just(listOf(
CategoryTitle("The Hobbit"),
Movie("An Unexpected Journey",
"https://www.imdb.com/title/tt0903624/",
Expand Down
Loading

0 comments on commit 5a5c514

Please sign in to comment.