├── sample
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── drawable-xxxhdpi
│ │ │ │ ├── img_11.jpg
│ │ │ │ ├── ic_right.png
│ │ │ │ ├── img_00.webp
│ │ │ │ ├── img_01.webp
│ │ │ │ ├── img_10.webp
│ │ │ │ └── ic_fab_done.png
│ │ │ ├── drawable
│ │ │ │ ├── avatar_drakeet.jpg
│ │ │ │ ├── square_border.xml
│ │ │ │ ├── shadow.xml
│ │ │ │ ├── square_background.xml
│ │ │ │ └── card.xml
│ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── layout
│ │ │ │ ├── item_weibo_simple_text.xml
│ │ │ │ ├── item_weibo_simple_image.xml
│ │ │ │ ├── item_horizontal_list.xml
│ │ │ │ ├── item_inflated_text.xml
│ │ │ │ ├── item_horizontal_post.xml
│ │ │ │ ├── item_square.xml
│ │ │ │ ├── item_image.xml
│ │ │ │ ├── item_data_type1.xml
│ │ │ │ ├── item_data_type2.xml
│ │ │ │ ├── item_text.xml
│ │ │ │ ├── activity_list.xml
│ │ │ │ ├── activity_multi_selectable.xml
│ │ │ │ ├── item_post.xml
│ │ │ │ ├── item_heavy.xml
│ │ │ │ ├── item_category.xml
│ │ │ │ ├── item_weibo_frame.xml
│ │ │ │ └── activity_more_apis_playground.xml
│ │ │ ├── values
│ │ │ │ ├── colors.xml
│ │ │ │ ├── strings.xml
│ │ │ │ ├── dimens.xml
│ │ │ │ └── styles.xml
│ │ │ ├── values-w820dp
│ │ │ │ └── dimens.xml
│ │ │ ├── color
│ │ │ │ └── square_number.xml
│ │ │ └── menu
│ │ │ │ └── menu_main.xml
│ │ ├── kotlin
│ │ │ └── com
│ │ │ │ └── drakeet
│ │ │ │ └── multitype
│ │ │ │ └── sample
│ │ │ │ ├── Numbers.kt
│ │ │ │ ├── Test.java
│ │ │ │ ├── common
│ │ │ │ ├── Category.kt
│ │ │ │ └── CategoryHolderInflater.kt
│ │ │ │ ├── normal
│ │ │ │ ├── ImageItem.kt
│ │ │ │ ├── RichItem.kt
│ │ │ │ ├── RichView.kt
│ │ │ │ ├── TextItem.kt
│ │ │ │ ├── ImageItemViewBinder.kt
│ │ │ │ ├── RichViewDelegate.kt
│ │ │ │ ├── TextItemViewBinder.kt
│ │ │ │ └── NormalActivity.kt
│ │ │ │ ├── payload
│ │ │ │ ├── HeavyItem.kt
│ │ │ │ ├── TestPayloadActivity.kt
│ │ │ │ └── HeavyItemViewBinder.kt
│ │ │ │ ├── bilibili
│ │ │ │ ├── Post.kt
│ │ │ │ ├── PostList.kt
│ │ │ │ ├── PostItemDecoration.kt
│ │ │ │ ├── PostViewBinder.kt
│ │ │ │ ├── PostsAdapter.kt
│ │ │ │ ├── HorizontalPostsHolderInflater.kt
│ │ │ │ └── BilibiliActivity.kt
│ │ │ │ ├── selectable
│ │ │ │ ├── Square.kt
│ │ │ │ ├── SquareViewBinder.kt
│ │ │ │ └── MultiSelectableActivity.kt
│ │ │ │ ├── weibo
│ │ │ │ ├── User.kt
│ │ │ │ ├── WeiboContent.kt
│ │ │ │ ├── Weibo.kt
│ │ │ │ ├── content
│ │ │ │ │ ├── SimpleText.kt
│ │ │ │ │ ├── SimpleImage.kt
│ │ │ │ │ ├── SimpleTextViewBinder.kt
│ │ │ │ │ └── SimpleImageViewBinder.kt
│ │ │ │ ├── WeiboJsonParser.kt
│ │ │ │ ├── ContentHolder.kt
│ │ │ │ ├── WeiboContentDeserializer.kt
│ │ │ │ ├── WeiboFrameBinder.kt
│ │ │ │ └── WeiboActivity.kt
│ │ │ │ ├── Savable.kt
│ │ │ │ ├── one2many
│ │ │ │ ├── Data.kt
│ │ │ │ ├── DataType1ViewBinder.kt
│ │ │ │ ├── DataType2ViewBinder.kt
│ │ │ │ └── OneDataToManyActivity.kt
│ │ │ │ ├── communication
│ │ │ │ ├── CommunicateWithBinderActivity.kt
│ │ │ │ └── TextItemWithOutsizeDataViewBinder.kt
│ │ │ │ ├── MenuBaseActivity.kt
│ │ │ │ └── more
│ │ │ │ └── MoreApisPlayground.kt
│ │ └── AndroidManifest.xml
│ └── androidTest
│ │ └── kotlin
│ │ └── com
│ │ └── drakeet
│ │ └── multitype
│ │ └── sample
│ │ ├── SmokeTest.kt
│ │ ├── one2many
│ │ ├── OneToManyTest.kt
│ │ └── DuplicateTypesTest.kt
│ │ ├── RecyclerViewMatcher.kt
│ │ └── bilibili
│ │ └── BilibiliActivityDataSetADCTest.kt
├── proguard-rules.pro
└── build.gradle
├── library
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ └── values
│ │ │ │ └── ids.xml
│ │ ├── kotlin
│ │ │ └── com
│ │ │ │ └── drakeet
│ │ │ │ └── multitype
│ │ │ │ ├── ViewHolderInflater.kt
│ │ │ │ ├── ViewHolderDelegate.kt
│ │ │ │ ├── ItemViewBinder.kt
│ │ │ │ ├── DefaultLinker.kt
│ │ │ │ ├── Type.kt
│ │ │ │ ├── DelegateNotFoundException.kt
│ │ │ │ ├── JavaClassLinker.kt
│ │ │ │ ├── OneToManyFlow.kt
│ │ │ │ ├── KotlinClassLinker.kt
│ │ │ │ ├── Linker.kt
│ │ │ │ ├── ClassLinkerBridge.kt
│ │ │ │ ├── MutableTypes.kt
│ │ │ │ ├── OneToManyBuilder.kt
│ │ │ │ ├── Types.kt
│ │ │ │ ├── ViewDelegate.kt
│ │ │ │ └── OneToManyEndpoint.kt
│ │ └── AndroidManifest.xml
│ └── test
│ │ └── kotlin
│ │ └── com
│ │ └── drakeet
│ │ └── multitype
│ │ ├── TestItem.kt
│ │ ├── TestItemViewDelegate.kt
│ │ ├── StringViewDelegate.kt
│ │ ├── MutableTypesTest.kt
│ │ ├── ItemViewDelegateTest.kt
│ │ ├── MultiTypeTest.kt
│ │ ├── OneToManyBuilderTest.kt
│ │ └── MultiTypeAdapterTest.kt
├── module.md
├── gradle.properties
└── build.gradle
├── image
├── sample-one2many.png
├── screenshot-normal.png
├── screenshot-bilibili.png
└── screenshot-multigrid.png
├── gradle
├── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
└── publish-docs.gradle
├── findbugs.xml
├── .github
├── CONTRIBUTING.md
└── ISSUE_TEMPLATE.md
├── .gitignore
├── RELEASING.md
├── settings.gradle
├── .travis.yml
├── CONTRIBUTING.md
├── gradle.properties
├── CHANGELOG.md
└── gradlew.bat
/sample/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/library/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/image/sample-one2many.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drakeet/MultiType/HEAD/image/sample-one2many.png
--------------------------------------------------------------------------------
/image/screenshot-normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drakeet/MultiType/HEAD/image/screenshot-normal.png
--------------------------------------------------------------------------------
/image/screenshot-bilibili.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drakeet/MultiType/HEAD/image/screenshot-bilibili.png
--------------------------------------------------------------------------------
/image/screenshot-multigrid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drakeet/MultiType/HEAD/image/screenshot-multigrid.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drakeet/MultiType/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxxhdpi/img_11.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drakeet/MultiType/HEAD/sample/src/main/res/drawable-xxxhdpi/img_11.jpg
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/avatar_drakeet.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drakeet/MultiType/HEAD/sample/src/main/res/drawable/avatar_drakeet.jpg
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drakeet/MultiType/HEAD/sample/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drakeet/MultiType/HEAD/sample/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxxhdpi/ic_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drakeet/MultiType/HEAD/sample/src/main/res/drawable-xxxhdpi/ic_right.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxxhdpi/img_00.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drakeet/MultiType/HEAD/sample/src/main/res/drawable-xxxhdpi/img_00.webp
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxxhdpi/img_01.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drakeet/MultiType/HEAD/sample/src/main/res/drawable-xxxhdpi/img_01.webp
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxxhdpi/img_10.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drakeet/MultiType/HEAD/sample/src/main/res/drawable-xxxhdpi/img_10.webp
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drakeet/MultiType/HEAD/sample/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drakeet/MultiType/HEAD/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drakeet/MultiType/HEAD/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/library/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxxhdpi/ic_fab_done.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drakeet/MultiType/HEAD/sample/src/main/res/drawable-xxxhdpi/ic_fab_done.png
--------------------------------------------------------------------------------
/library/module.md:
--------------------------------------------------------------------------------
1 | # Module multitype
2 |
3 | An Android library to create multiple item types list views easily and flexibly
4 |
5 | # Package me.drakeet.multitype
6 |
7 | An Android library to create multiple item types list views easily and flexibly
8 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/Numbers.kt:
--------------------------------------------------------------------------------
1 | package com.drakeet.multitype.sample
2 |
3 | import android.content.res.Resources
4 |
5 | /**
6 | * @author Drakeet Xu
7 | */
8 | val Number.dp: Int get() = (toInt() * Resources.getSystem().displayMetrics.density).toInt()
9 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/Test.java:
--------------------------------------------------------------------------------
1 | package com.drakeet.multitype.sample;
2 |
3 | import com.drakeet.multitype.MultiTypeAdapter;
4 |
5 | /**
6 | * @author Drakeet Xu
7 | */
8 | class Test {
9 | MultiTypeAdapter adapter = new MultiTypeAdapter();
10 | }
11 |
--------------------------------------------------------------------------------
/library/src/main/kotlin/com/drakeet/multitype/ViewHolderInflater.kt:
--------------------------------------------------------------------------------
1 | package com.drakeet.multitype
2 |
3 | import androidx.recyclerview.widget.RecyclerView
4 |
5 | /**
6 | * @author Drakeet Xu
7 | */
8 | abstract class ViewHolderInflater : ItemViewBinder()
9 |
--------------------------------------------------------------------------------
/library/src/main/kotlin/com/drakeet/multitype/ViewHolderDelegate.kt:
--------------------------------------------------------------------------------
1 | package com.drakeet.multitype
2 |
3 | import androidx.recyclerview.widget.RecyclerView
4 |
5 | /**
6 | * @author Drakeet Xu
7 | */
8 | abstract class ViewHolderDelegate: ItemViewDelegate()
9 |
--------------------------------------------------------------------------------
/findbugs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | If you would like to contribute code to MultiType you can do so through GitHub by
4 | forking the repository and sending a pull request.
5 |
6 | When submitting code, please make every effort to follow existing conventions
7 | and style in order to keep the code as readable as possible. Please also make
8 | sure your code compiles by running `./gradlew clean build` and Checkstyle with
9 | `/checkstyle.xml`.
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # built application files
2 | *.ap_
3 |
4 | # files for the dex VM
5 | *.dex
6 |
7 | # Java class files
8 | *.class
9 |
10 | # generated files
11 | bin/
12 | gen/
13 |
14 | # Local configuration file (sdk path, etc)
15 | local.properties
16 |
17 | # Proguard folder generated by Eclipse
18 | proguard/
19 |
20 | # Ignore gradle files
21 | .gradle/
22 | build/
23 |
24 | # Eclipse project files
25 | .classpath
26 | .project
27 | .settings/
28 |
29 | # Intellij project files
30 | *.iml
31 | *.ipr
32 | *.iws
33 | .idea/
34 |
35 | # Mac system files
36 | .DS_Store
37 |
38 | *.keystore
--------------------------------------------------------------------------------
/RELEASING.md:
--------------------------------------------------------------------------------
1 | Releasing
2 | =========
3 |
4 | 1. Change the version in `gradle.properties` to a non-SNAPSHOT version.
5 | 2. Update the `CHANGELOG.md` for the impending release
6 | 3. Update the `README.md` with the new version.
7 | 4. `git commit -am "Prepare for release X.Y.Z"` (where X.Y.Z is the new version)
8 | 5. `git tag -a X.Y.Z -m "Version X.Y.Z"` (where X.Y.Z is the new version)
9 | 6. `./gradlew clean uploadArchives`
10 | 7. Update the `gradle.properties` to the next SNAPSHOT version.
11 | 8. `git commit -am "Prepare next development version"`
12 | 9. `git push && git push --tags`
13 | 10. Visit [Sonatype Nexus](https://oss.sonatype.org/) and promote the artifact.
14 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | include ':sample'
17 | include ':library'
18 |
--------------------------------------------------------------------------------
/sample/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/drakeet/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/library/src/main/kotlin/com/drakeet/multitype/ItemViewBinder.kt:
--------------------------------------------------------------------------------
1 | package com.drakeet.multitype
2 |
3 | import android.content.Context
4 | import android.view.LayoutInflater
5 | import android.view.ViewGroup
6 | import androidx.recyclerview.widget.RecyclerView
7 |
8 | /**
9 | * This is a compatible version of [ItemViewDelegate].
10 | * @see ItemViewDelegate
11 | * @author Drakeet Xu
12 | */
13 | abstract class ItemViewBinder : ItemViewDelegate() {
14 |
15 | final override fun onCreateViewHolder(context: Context, parent: ViewGroup): VH {
16 | return onCreateViewHolder(LayoutInflater.from(context), parent)
17 | }
18 |
19 | abstract fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): VH
20 | }
21 |
--------------------------------------------------------------------------------
/library/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/library/src/test/kotlin/com/drakeet/multitype/TestItem.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype
18 |
19 | /**
20 | * @author Drakeet Xu
21 | */
22 | open class TestItem(val text: String)
23 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/common/Category.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.common
18 |
19 | /**
20 | * @author Drakeet Xu
21 | */
22 | class Category(var title: String)
23 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/normal/ImageItem.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.normal
18 |
19 | /**
20 | * @author Drakeet Xu
21 | */
22 | class ImageItem(val resId: Int)
23 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/payload/HeavyItem.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.payload
18 |
19 | /**
20 | * @author Drakeet Xu
21 | */
22 | class HeavyItem(var text: String)
23 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/bilibili/Post.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.bilibili
18 |
19 | /**
20 | * @author Drakeet Xu
21 | */
22 | class Post(var coverResId: Int, var title: String)
23 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/bilibili/PostList.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.bilibili
18 |
19 | /**
20 | * @author Drakeet Xu
21 | */
22 | class PostList(internal val posts: List)
23 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/normal/RichItem.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.normal
18 |
19 | /**
20 | * @author Drakeet Xu
21 | */
22 | class RichItem(var text: String, var imageResId: Int)
23 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/selectable/Square.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.selectable
18 |
19 | /**
20 | * @author Drakeet Xu
21 | */
22 | class Square(val number: Int) {
23 | var isSelected: Boolean = false
24 | }
25 |
--------------------------------------------------------------------------------
/library/src/main/kotlin/com/drakeet/multitype/DefaultLinker.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype
18 |
19 | /**
20 | * @author Drakeet Xu
21 | */
22 | internal class DefaultLinker : Linker {
23 | override fun index(position: Int, item: T): Int = 0
24 | }
25 |
--------------------------------------------------------------------------------
/library/src/main/kotlin/com/drakeet/multitype/Type.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype
18 |
19 | /**
20 | * @author Drakeet Xu
21 | */
22 | data class Type(
23 | val clazz: Class,
24 | val delegate: ItemViewDelegate,
25 | val linker: Linker
26 | )
27 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/weibo/User.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.weibo
18 |
19 | import androidx.annotation.DrawableRes
20 |
21 | /**
22 | * @author Drakeet Xu
23 | */
24 | class User(var name: String, @field:DrawableRes var avatar: Int)
25 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/Savable.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample
18 |
19 | /**
20 | * @author Drakeet Xu
21 | */
22 | interface Savable {
23 |
24 | fun init(data: ByteArray)
25 |
26 | fun toBytes(): ByteArray
27 |
28 | fun describe(): String
29 | }
30 |
--------------------------------------------------------------------------------
/library/src/main/kotlin/com/drakeet/multitype/DelegateNotFoundException.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype
18 |
19 | /**
20 | * @author Drakeet Xu
21 | */
22 | internal class DelegateNotFoundException(clazz: Class<*>) : RuntimeException(
23 | "Have you registered the ${clazz.name} type and its delegate or binder?"
24 | )
25 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/square_border.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
20 |
21 |
24 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: android
2 | jdk: oraclejdk8
3 |
4 | env:
5 | global:
6 | - ANDROID_ABI=armeabi-v7a
7 |
8 | android:
9 | components:
10 | - tools
11 | - android-22
12 | - android-28
13 | - sys-img-armeabi-v7a-android-22
14 | - extra-android-m2repository
15 | - extra-android-support
16 | - extra
17 | licenses:
18 | - android-sdk-license-.+
19 |
20 | before_install:
21 | # Install SDK license so Android Gradle plugin can install deps.
22 | - mkdir "$ANDROID_HOME/licenses" || true
23 | - echo "d56f5187479451eabf01fb78af6dfcb131a6481e" > "$ANDROID_HOME/licenses/android-sdk-license"
24 | - echo "24333f8a63b6825ea9c5514f83c2829b004d1fee" >> "$ANDROID_HOME/licenses/android-sdk-license"
25 |
26 | before_script:
27 | - chmod +x gradlew
28 | - echo no | android create avd --force -n test -t android-22 --abi $ANDROID_ABI
29 | - emulator -avd test -no-window &
30 | - android-wait-for-emulator
31 | - adb shell input keyevent 82 &
32 |
33 | script:
34 | - ./gradlew clean connectedAndroidTest
35 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_weibo_simple_text.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
23 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/weibo/WeiboContent.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.weibo
18 |
19 | import com.google.gson.annotations.SerializedName
20 |
21 | /**
22 | * @author Drakeet Xu
23 | */
24 | abstract class WeiboContent protected constructor(
25 | @field:SerializedName("content_type")
26 | val contentType: String
27 | )
28 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_weibo_simple_image.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
23 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/weibo/Weibo.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.weibo
18 |
19 | /**
20 | * @author Drakeet Xu
21 | */
22 | class Weibo(var user: User, var content: WeiboContent) {
23 |
24 | var createTime: String = "Just now"
25 |
26 | override fun toString(): String {
27 | return "content: " + content.javaClass.simpleName
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/weibo/content/SimpleText.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.weibo.content
18 |
19 | import com.drakeet.multitype.sample.weibo.WeiboContent
20 |
21 | /**
22 | * @author Drakeet Xu
23 | */
24 | class SimpleText(var text: String) : WeiboContent(TYPE) {
25 | companion object {
26 | const val TYPE = "simple_text"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | #FF4081
20 | #ce3066
21 | #FF4081
22 | #E07679
23 | #de000000
24 |
25 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | What kind of issue is this?
2 |
3 | - [ ] Question. This issue tracker is not the place for questions. If you want to ask how to do
4 | something, or to understand why something isn't working the way you expect it to, use Stack
5 | Overflow. https://stackoverflow.com/questions/tagged/MultiType
6 |
7 | - [ ] Bug report. If you’ve found a bug, spend the time to write a failing test. Please provide
8 | your device name, device OS version, and describe the reproduction steps.
9 |
10 | - [ ] Feature Request. Start by telling us what problem you’re trying to solve. Often a solution
11 | already exists! Don’t send pull requests to implement new features without first getting our
12 | support. Sometimes we leave features out on purpose to keep the project small.
13 |
14 | ###### Info:
15 |
16 | - MultiType version:
17 | - Device OS version:
18 | - Device Name:
19 |
20 | ###### Description:
21 |
22 | ###### Reproduction Steps:
23 |
24 | ###### My thoughts:
25 |
26 | ###### What did I do:
27 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/shadow.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
21 |
22 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_horizontal_list.xml:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/normal/RichView.kt:
--------------------------------------------------------------------------------
1 | package com.drakeet.multitype.sample.normal
2 |
3 | import android.content.Context
4 | import android.graphics.Color
5 | import android.view.Gravity
6 | import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
7 | import android.widget.LinearLayout
8 | import androidx.appcompat.widget.AppCompatImageView
9 | import androidx.appcompat.widget.AppCompatTextView
10 | import com.drakeet.multitype.sample.R
11 | import com.drakeet.multitype.sample.dp
12 |
13 | /**
14 | * @author Drakeet Xu
15 | */
16 | class RichView(context: Context) : LinearLayout(context) {
17 |
18 | val imageView = AppCompatImageView(context).apply {
19 | addView(this, LayoutParams(72.dp, 72.dp))
20 | }
21 |
22 | val textView = AppCompatTextView(context).apply {
23 | gravity = Gravity.CENTER
24 | setTextColor(Color.BLACK)
25 | addView(this, LayoutParams(WRAP_CONTENT, WRAP_CONTENT))
26 | }
27 |
28 | init {
29 | orientation = VERTICAL
30 | gravity = Gravity.CENTER
31 | setPadding(16.dp, 16.dp, 16.dp, 16.dp)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/sample/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
21 | 64dp
22 |
23 |
--------------------------------------------------------------------------------
/sample/src/main/res/color/square_number.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
21 |
22 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_inflated_text.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
26 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 | MultiType
19 | MT: Bilibili
20 | MT: MultiGrid
21 | close
22 | ADD
23 | REMOVE
24 | CLEAR
25 |
26 |
--------------------------------------------------------------------------------
/gradle/publish-docs.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018. Uber Technologies
3 | * Copyright (c) 2018 Drakeet Xu
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | configurations {
19 | osstrich
20 | }
21 |
22 | dependencies {
23 | osstrich 'com.squareup.osstrich:osstrich:1.3.0'
24 | }
25 |
26 | task publishDocs(type: JavaExec) {
27 | classpath = configurations.osstrich
28 | main = 'com.squareup.osstrich.JavadocPublisher'
29 | args = ['build/javadoc',
30 | 'https://github.com/drakeet/MultiType',
31 | 'com.drakeet.multitype']
32 | }
33 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/one2many/Data.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.one2many
18 |
19 | import com.google.gson.annotations.SerializedName
20 |
21 | /**
22 | * @author Drakeet Xu
23 | */
24 | class Data(
25 | @field:SerializedName("title") var title: String,
26 | @field:SerializedName("type") var type: Int
27 | ) {
28 |
29 | companion object {
30 | const val TYPE_1 = 1
31 | const val TYPE_2 = 2
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/weibo/content/SimpleImage.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.weibo.content
18 |
19 | import androidx.annotation.DrawableRes
20 | import com.drakeet.multitype.sample.weibo.WeiboContent
21 |
22 | /**
23 | * @author Drakeet Xu
24 | */
25 | class SimpleImage(
26 | @param:DrawableRes @field:DrawableRes var resId: Int
27 | ) : WeiboContent(TYPE) {
28 |
29 | companion object {
30 | const val TYPE = "simple_image"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/square_background.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 | -
20 |
21 |
22 |
23 | -
24 |
25 |
26 |
27 | -
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_horizontal_post.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
23 |
24 |
28 |
29 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to MultiType
2 |
3 | If you would like to contribute code you can do so through GitHub by forking the repository and sending a pull request.
4 |
5 | When submitting code, please make every effort to follow existing conventions and style in order to keep the code as readable as possible.
6 |
7 | ## License
8 |
9 | By contributing your code, you agree to license your contribution under the terms of the APLv2: https://github.com/drakeet/MultiType/blob/4.x/LICENSE
10 |
11 | All files are released with the Apache 2.0 license.
12 |
13 | If you are adding a new file it should have a header like this:
14 |
15 | ```
16 | /*
17 | * Licensed under the Apache License, Version 2.0 (the "License");
18 | * you may not use this file except in compliance with the License.
19 | * You may obtain a copy of the License at
20 | *
21 | * http://www.apache.org/licenses/LICENSE-2.0
22 | *
23 | * Unless required by applicable law or agreed to in writing, software
24 | * distributed under the License is distributed on an "AS IS" BASIS,
25 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26 | * See the License for the specific language governing permissions and
27 | * limitations under the License.
28 | */
29 | ```
30 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_square.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
25 |
26 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 | 16dp
20 | 16dp
21 | 2dp
22 | 6dp
23 |
24 | 24dp
25 | 12dp
26 | 6dp
27 | 96dp
28 |
29 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/weibo/WeiboJsonParser.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.weibo
18 |
19 | import com.google.gson.GsonBuilder
20 | import com.google.gson.reflect.TypeToken
21 | import java.util.*
22 |
23 | /**
24 | * @author Drakeet Xu
25 | */
26 | internal object WeiboJsonParser {
27 |
28 | val GSON = GsonBuilder()
29 | .registerTypeAdapter(WeiboContent::class.java, WeiboContentDeserializer())
30 | .create()!!
31 |
32 | fun fromJson(json: String): List {
33 | return GSON.fromJson(json, object : TypeToken>() {}.type)
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_image.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
25 |
26 |
31 |
32 |
--------------------------------------------------------------------------------
/library/src/main/kotlin/com/drakeet/multitype/JavaClassLinker.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype
18 |
19 | /**
20 | * An interface to link the items and delegates by the classes of delegates.
21 | *
22 | * @author Drakeet Xu
23 | */
24 | interface JavaClassLinker {
25 |
26 | /**
27 | * Returns the class of your registered delegates for your item.
28 | *
29 | * @param position The position in items
30 | * @param item The item
31 | * @return The index of your registered delegates
32 | * @see OneToManyEndpoint.withJavaClassLinker
33 | */
34 | fun index(position: Int, item: T): Class>
35 | }
36 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/card.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
21 |
22 | -
23 |
24 |
25 |
26 |
27 |
28 |
29 | -
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/library/src/main/kotlin/com/drakeet/multitype/OneToManyFlow.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype
18 |
19 | import androidx.annotation.CheckResult
20 |
21 | /**
22 | * Process and flow operators for one-to-many.
23 | *
24 | * @author Drakeet Xu
25 | */
26 | interface OneToManyFlow {
27 |
28 | /**
29 | * Sets some item view delegates to the item type.
30 | *
31 | * @param delegates the item view delegates
32 | * @return end flow operator
33 | */
34 | @CheckResult
35 | fun to(vararg delegates: ItemViewDelegate): OneToManyEndpoint
36 |
37 | @CheckResult
38 | fun to(vararg delegates: ItemViewBinder): OneToManyEndpoint
39 | }
40 |
--------------------------------------------------------------------------------
/library/src/main/kotlin/com/drakeet/multitype/KotlinClassLinker.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype
18 |
19 | import kotlin.reflect.KClass
20 |
21 | /**
22 | * An interface to link the items and delegates by the classes of delegates.
23 | *
24 | * @author Drakeet Xu
25 | */
26 | interface KotlinClassLinker {
27 |
28 | /**
29 | * Returns the class of your registered delegates for your item.
30 | *
31 | * @param position The position in items
32 | * @param item The item
33 | * @return The index of your registered delegates
34 | * @see OneToManyEndpoint.withJavaClassLinker
35 | */
36 | fun index(position: Int, item: T): KClass>
37 | }
38 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/weibo/ContentHolder.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.weibo
18 |
19 | import android.view.View
20 |
21 | /**
22 | * @author Drakeet Xu
23 | */
24 | open class ContentHolder(val itemView: View) {
25 |
26 | lateinit var parent: WeiboFrameBinder.FrameHolder
27 |
28 | val absoluteAdapterPosition: Int
29 | get() = parent.absoluteAdapterPosition
30 |
31 | val layoutPosition: Int
32 | get() = parent.layoutPosition
33 |
34 | val oldPosition: Int
35 | get() = parent.oldPosition
36 |
37 | var isRecyclable: Boolean
38 | get() = parent.isRecyclable
39 | set(recyclable) = parent.setIsRecyclable(recyclable)
40 | }
41 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_data_type1.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
24 |
25 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_data_type2.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
24 |
25 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/library/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2016-present. Drakeet Xu
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 |
17 | POM_NAME=MultiType
18 | POM_ARTIFACT_ID=multitype
19 | POM_PACKAGING=aar
20 |
21 | GROUP=com.drakeet.multitype
22 |
23 | POM_DESCRIPTION=Easier and more flexible to create multiple types for Android RecyclerView.
24 | POM_URL=https://github.com/drakeet/MultiType
25 | POM_SCM_URL=https://github.com/drakeet/MultiType
26 | POM_SCM_CONNECTION=scm:git@github.com:drakeet/MultiType.git
27 | POM_SCM_DEV_CONNECTION=scm:git@github.com:drakeet/MultiType.git
28 | POM_LICENCE_NAME=The Apache Software License, Version 2.0
29 | POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
30 | POM_LICENCE_DIST=repo
31 | POM_DEVELOPER_ID=drakeet
32 | POM_DEVELOPER_NAME=Drakeet Xu
33 | POM_DEVELOPER_URL=https://drakeet.com
34 |
--------------------------------------------------------------------------------
/library/src/test/kotlin/com/drakeet/multitype/TestItemViewDelegate.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype
18 |
19 | import android.content.Context
20 | import android.view.View
21 | import android.view.ViewGroup
22 | import androidx.recyclerview.widget.RecyclerView
23 |
24 | /**
25 | * @author Drakeet Xu
26 | */
27 | open class TestItemViewDelegate : ItemViewDelegate() {
28 |
29 | override fun onCreateViewHolder(context: Context, parent: ViewGroup): ViewHolder {
30 | throw NotImplementedError()
31 | }
32 |
33 | override fun onBindViewHolder(holder: ViewHolder, item: TestItem) {}
34 |
35 | inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
36 | }
37 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_text.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
25 |
26 |
33 |
34 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/activity_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
25 |
26 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2016-present. Drakeet Xu
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 |
17 | # Project-wide Gradle settings.
18 |
19 | # IDE (e.g. Android Studio) users:
20 | # Gradle settings configured through the IDE *will override*
21 | # any settings specified in this file.
22 |
23 | # For more details on how to configure your build environment visit
24 | # http://www.gradle.org/docs/current/userguide/build_environment.html
25 |
26 | # Specifies the JVM arguments used for the daemon process.
27 | # The setting is particularly useful for tweaking memory settings.
28 | android.useAndroidX=true
29 | org.gradle.jvmargs=-Xmx4096m
30 |
31 | # When configured, Gradle will run in incubating parallel mode.
32 | # This option should only be used with decoupled projects. More details, visit
33 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
34 | # org.gradle.parallel=true
35 |
--------------------------------------------------------------------------------
/library/src/test/kotlin/com/drakeet/multitype/StringViewDelegate.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype
18 |
19 | import android.R
20 | import android.content.Context
21 | import android.view.LayoutInflater
22 | import android.view.View
23 | import android.view.ViewGroup
24 | import androidx.recyclerview.widget.RecyclerView
25 |
26 | /**
27 | * @author Drakeet Xu
28 | */
29 | class StringViewDelegate : ItemViewDelegate() {
30 |
31 | override fun onCreateViewHolder(context: Context, parent: ViewGroup): ViewHolder {
32 | return ViewHolder(LayoutInflater.from(context).inflate(R.layout.test_list_item, parent, false))
33 | }
34 |
35 | override fun onBindViewHolder(holder: ViewHolder, item: String) {}
36 |
37 | class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
38 | }
39 |
--------------------------------------------------------------------------------
/library/src/main/kotlin/com/drakeet/multitype/Linker.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype
18 |
19 | import androidx.annotation.IntRange
20 |
21 | /**
22 | * An interface to link the items and delegates by the array index.
23 | *
24 | * @author Drakeet Xu
25 | */
26 | interface Linker {
27 |
28 | /**
29 | * Returns the index of your registered delegates for your item. The result should be in range of
30 | * `[0, one-to-multiple-delegates.length)`.
31 | *
32 | * Note: The argument of [OneToManyFlow.to] is the
33 | * one-to-multiple-delegates.
34 | *
35 | * @param position The position in items
36 | * @param item The data item
37 | * @return The index of your registered delegates
38 | * @see OneToManyFlow.to
39 | * @see OneToManyEndpoint.withLinker
40 | */
41 | @IntRange(from = 0)
42 | fun index(position: Int, item: T): Int
43 | }
44 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/bilibili/PostItemDecoration.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.bilibili
18 |
19 | import android.graphics.Rect
20 | import android.view.View
21 | import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup
22 | import androidx.recyclerview.widget.RecyclerView
23 |
24 | /**
25 | * @author Drakeet Xu
26 | */
27 | class PostItemDecoration(private val space: Int, private val spanSizeLookup: SpanSizeLookup) : RecyclerView.ItemDecoration() {
28 |
29 | override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
30 | val position = parent.getChildLayoutPosition(view)
31 | if (spanSizeLookup.getSpanSize(position) == 1) {
32 | outRect.left = space
33 | if (position % 2 == 0) {
34 | outRect.right = space
35 | }
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/normal/TextItem.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.normal
18 |
19 | import com.google.gson.Gson
20 | import com.drakeet.multitype.sample.Savable
21 | import java.nio.charset.Charset
22 |
23 | /**
24 | * @author Drakeet Xu
25 | */
26 | class TextItem : Savable {
27 |
28 | lateinit var text: String
29 |
30 | constructor(text: String) {
31 | this.text = text
32 | }
33 |
34 | constructor(data: ByteArray) {
35 | init(data)
36 | }
37 |
38 | override fun init(data: ByteArray) {
39 | val json = String(data, UTF_8)
40 | this.text = Gson().fromJson(json, TextItem::class.java).text
41 | }
42 |
43 | override fun toBytes(): ByteArray {
44 | return Gson().toJson(this).toByteArray(UTF_8)
45 | }
46 |
47 | override fun describe(): String {
48 | return "Text"
49 | }
50 |
51 | companion object {
52 | private val UTF_8 = Charset.forName("UTF-8")
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/activity_multi_selectable.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
25 |
26 |
33 |
34 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_post.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
23 |
24 |
30 |
31 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/library/src/main/kotlin/com/drakeet/multitype/ClassLinkerBridge.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype
18 |
19 | /**
20 | * @author Drakeet Xu
21 | */
22 | internal class ClassLinkerBridge private constructor(
23 | private val javaClassLinker: JavaClassLinker,
24 | private val delegates: Array>
25 | ) : Linker {
26 |
27 | override fun index(position: Int, item: T): Int {
28 | val indexedClass = javaClassLinker.index(position, item)
29 | val index = delegates.indexOfFirst { it.javaClass == indexedClass }
30 | if (index != -1) return index
31 | throw IndexOutOfBoundsException(
32 | "The delegates'(${delegates.contentToString()}) you registered do not contain this ${indexedClass.name}."
33 | )
34 | }
35 |
36 | companion object {
37 | fun toLinker(
38 | javaClassLinker: JavaClassLinker,
39 | delegates: Array>
40 | ): Linker {
41 | return ClassLinkerBridge(javaClassLinker, delegates)
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/library/src/main/kotlin/com/drakeet/multitype/MutableTypes.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype
18 |
19 | /**
20 | * A TypePool implemented by an ArrayList.
21 | *
22 | * @author Drakeet Xu
23 | */
24 | open class MutableTypes constructor(
25 | open val initialCapacity: Int = 0,
26 | open val types: MutableList> = ArrayList(initialCapacity)
27 | ) : Types {
28 |
29 | override val size: Int get() = types.size
30 |
31 | override fun register(type: Type) {
32 | types.add(type)
33 | }
34 |
35 | override fun unregister(clazz: Class<*>): Boolean {
36 | return types.removeAll { it.clazz == clazz }
37 | }
38 |
39 | @Suppress("UNCHECKED_CAST")
40 | override fun getType(index: Int): Type = types[index] as Type
41 |
42 | override fun firstIndexOf(clazz: Class<*>): Int {
43 | val index = types.indexOfFirst { it.clazz == clazz }
44 | if (index != -1) {
45 | return index
46 | }
47 | return types.indexOfFirst { it.clazz.isAssignableFrom(clazz) }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/common/CategoryHolderInflater.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.common
18 |
19 | import android.view.LayoutInflater
20 | import android.view.View
21 | import android.view.ViewGroup
22 | import android.widget.TextView
23 | import androidx.recyclerview.widget.RecyclerView
24 | import com.drakeet.multitype.ViewHolderInflater
25 | import com.drakeet.multitype.sample.R
26 |
27 | /**
28 | * @author Drakeet Xu
29 | */
30 | class CategoryHolderInflater : ViewHolderInflater() {
31 |
32 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): ViewHolder {
33 | return ViewHolder(inflater.inflate(R.layout.item_category, parent, false))
34 | }
35 |
36 | override fun onBindViewHolder(holder: ViewHolder, item: Category) {
37 | holder.title.text = item.title
38 | }
39 |
40 | class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
41 | val title: TextView = itemView.findViewById(R.id.title)
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/library/src/test/kotlin/com/drakeet/multitype/MutableTypesTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype
18 |
19 | import com.google.common.truth.Truth.assertThat
20 | import org.junit.Before
21 | import org.junit.Test
22 |
23 | /**
24 | * @author Drakeet Xu
25 | */
26 | class MutableTypesTest {
27 |
28 | private lateinit var types: MutableTypes
29 |
30 | private inner class SubClass(text: String) : TestItem(text)
31 |
32 | private inner class RegisteredSubClass(text: String) : TestItem(text)
33 |
34 | @Before
35 | fun register() {
36 | types = MutableTypes()
37 | types.register(Type(TestItem::class.java, TestItemViewDelegate(), DefaultLinker()))
38 | types.register(Type(RegisteredSubClass::class.java, TestItemViewDelegate(), DefaultLinker()))
39 | }
40 |
41 | @Test
42 | fun testFirstIndexOf() {
43 | assertThat(types.firstIndexOf(TestItem::class.java)).isEqualTo(0)
44 | assertThat(types.firstIndexOf(SubClass::class.java)).isEqualTo(0)
45 | assertThat(types.firstIndexOf(RegisteredSubClass::class.java)).isEqualTo(1)
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/normal/ImageItemViewBinder.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.normal
18 |
19 | import android.view.LayoutInflater
20 | import android.view.View
21 | import android.view.ViewGroup
22 | import android.widget.ImageView
23 | import androidx.recyclerview.widget.RecyclerView
24 | import com.drakeet.multitype.ItemViewBinder
25 | import com.drakeet.multitype.sample.R
26 |
27 | /**
28 | * @author Drakeet Xu
29 | */
30 | class ImageItemViewBinder : ItemViewBinder() {
31 |
32 | inner class ImageHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
33 | val image: ImageView = itemView.findViewById(R.id.image)
34 |
35 | }
36 |
37 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): ImageHolder {
38 | return ImageHolder(inflater.inflate(R.layout.item_image, parent, false))
39 | }
40 |
41 | override fun onBindViewHolder(holder: ImageHolder, item: ImageItem) {
42 | holder.image.setImageResource(item.resId)
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/weibo/content/SimpleTextViewBinder.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.weibo.content
18 |
19 | import android.view.LayoutInflater
20 | import android.view.View
21 | import android.view.ViewGroup
22 | import android.widget.TextView
23 | import com.drakeet.multitype.sample.R
24 | import com.drakeet.multitype.sample.weibo.ContentHolder
25 | import com.drakeet.multitype.sample.weibo.WeiboFrameBinder
26 |
27 | /**
28 | * @author Drakeet Xu
29 | */
30 | class SimpleTextViewBinder : WeiboFrameBinder() {
31 |
32 | override fun onCreateContentViewHolder(inflater: LayoutInflater, parent: ViewGroup): ContentHolder {
33 | return ViewHolder(inflater.inflate(R.layout.item_weibo_simple_text, parent, false))
34 | }
35 |
36 | override fun onBindContentViewHolder(holder: ViewHolder, content: SimpleText) {
37 | holder.simpleText.text = content.text
38 | }
39 |
40 | class ViewHolder(itemView: View) : ContentHolder(itemView) {
41 | val simpleText: TextView = itemView.findViewById(R.id.simple_text)
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_heavy.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
23 |
24 |
30 |
31 |
36 |
37 |
42 |
43 |
49 |
50 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/one2many/DataType1ViewBinder.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.one2many
18 |
19 | import android.view.LayoutInflater
20 | import android.view.View
21 | import android.view.ViewGroup
22 | import android.widget.TextView
23 | import androidx.recyclerview.widget.RecyclerView
24 | import com.drakeet.multitype.ItemViewBinder
25 | import com.drakeet.multitype.sample.R
26 |
27 | /**
28 | * Note: Data - DataType1ViewBinder
29 | *
30 | * @author Drakeet Xu
31 | */
32 | class DataType1ViewBinder : ItemViewBinder() {
33 |
34 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): ViewHolder {
35 | return ViewHolder(inflater.inflate(R.layout.item_data_type1, parent, false))
36 | }
37 |
38 | override fun onBindViewHolder(holder: ViewHolder, item: Data) {
39 | holder.setTitle(item.title)
40 | }
41 |
42 | class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
43 |
44 | private var titleView: TextView = itemView.findViewById(android.R.id.title)
45 |
46 | fun setTitle(title: String) {
47 | titleView.text = title
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/one2many/DataType2ViewBinder.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.one2many
18 |
19 | import android.view.LayoutInflater
20 | import android.view.View
21 | import android.view.ViewGroup
22 | import android.widget.TextView
23 | import androidx.recyclerview.widget.RecyclerView
24 | import com.drakeet.multitype.ItemViewBinder
25 | import com.drakeet.multitype.sample.R
26 |
27 | /**
28 | * Note: Data - DataType2ViewBinder
29 | *
30 | * @author Drakeet Xu
31 | */
32 | class DataType2ViewBinder : ItemViewBinder() {
33 |
34 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): ViewHolder {
35 | return ViewHolder(inflater.inflate(R.layout.item_data_type2, parent, false))
36 | }
37 |
38 | override fun onBindViewHolder(holder: DataType2ViewBinder.ViewHolder, item: Data) {
39 | holder.setTitle(item.title)
40 | }
41 |
42 | class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
43 |
44 | private var titleView: TextView = itemView.findViewById(android.R.id.title)
45 |
46 | fun setTitle(title: String) {
47 | titleView.text = title
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/weibo/WeiboContentDeserializer.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.weibo
18 |
19 | import com.google.gson.*
20 | import com.drakeet.multitype.sample.weibo.content.SimpleImage
21 | import com.drakeet.multitype.sample.weibo.content.SimpleText
22 | import java.lang.reflect.Type
23 |
24 | /**
25 | * @author Drakeet Xu
26 | */
27 | class WeiboContentDeserializer : JsonDeserializer {
28 |
29 | @Throws(JsonParseException::class)
30 | override fun deserialize(json: JsonElement, type: Type, context: JsonDeserializationContext): WeiboContent? {
31 | val gson = WeiboJsonParser.GSON
32 | val jsonObject = json as JsonObject
33 | val contentType = stringOrEmpty(jsonObject.get("content_type"))
34 | var content: WeiboContent? = null
35 |
36 | if (SimpleText.TYPE == contentType) {
37 | content = gson.fromJson(json, SimpleText::class.java)
38 | } else if (SimpleImage.TYPE == contentType) {
39 | content = gson.fromJson(json, SimpleImage::class.java)
40 | }
41 | return content
42 | }
43 |
44 | private fun stringOrEmpty(jsonElement: JsonElement): String {
45 | return if (jsonElement.isJsonNull) "" else jsonElement.asString
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/bilibili/PostViewBinder.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.bilibili
18 |
19 | import android.view.LayoutInflater
20 | import android.view.View
21 | import android.view.ViewGroup
22 | import android.widget.ImageView
23 | import android.widget.TextView
24 | import androidx.recyclerview.widget.RecyclerView
25 | import com.drakeet.multitype.ItemViewBinder
26 | import com.drakeet.multitype.sample.R
27 |
28 | /**
29 | * @author Drakeet Xu
30 | */
31 | class PostViewBinder : ItemViewBinder() {
32 |
33 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): ViewHolder {
34 | return ViewHolder(inflater.inflate(R.layout.item_post, parent, false))
35 | }
36 |
37 | override fun onBindViewHolder(holder: ViewHolder, item: Post) {
38 | holder.setData(item)
39 | }
40 |
41 | class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
42 |
43 | private val cover: ImageView = itemView.findViewById(R.id.cover)
44 | private val title: TextView = itemView.findViewById(R.id.title)
45 |
46 | fun setData(post: Post) {
47 | cover.setImageResource(post.coverResId)
48 | title.text = post.title
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/communication/CommunicateWithBinderActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.communication
18 |
19 | import android.os.Bundle
20 | import androidx.recyclerview.widget.RecyclerView
21 | import com.drakeet.multitype.MultiTypeAdapter
22 | import com.drakeet.multitype.sample.MenuBaseActivity
23 | import com.drakeet.multitype.sample.R
24 | import com.drakeet.multitype.sample.normal.TextItem
25 | import java.util.*
26 |
27 | /**
28 | * @author Drakeet Xu
29 | */
30 | class CommunicateWithBinderActivity : MenuBaseActivity() {
31 |
32 | private val aFieldValue = "aFieldValue of SimpleActivity"
33 | private var adapter: MultiTypeAdapter = MultiTypeAdapter()
34 |
35 | override fun onCreate(savedInstanceState: Bundle?) {
36 | super.onCreate(savedInstanceState)
37 | setContentView(R.layout.activity_list)
38 | val recyclerView = findViewById(R.id.list)
39 |
40 | val items = ArrayList()
41 | adapter.register(TextItemWithOutsizeDataViewBinder(aFieldValue))
42 | recyclerView.adapter = adapter
43 |
44 | for (i in 0..19) {
45 | items.add(TextItem(i.toString()))
46 | }
47 | adapter.items = items
48 | adapter.notifyDataSetChanged()
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_category.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
27 |
28 |
32 |
33 |
36 |
37 |
44 |
45 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/normal/RichViewDelegate.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.normal
18 |
19 | import android.annotation.SuppressLint
20 | import android.content.Context
21 | import android.view.Gravity
22 | import android.view.ViewGroup
23 | import android.view.ViewGroup.LayoutParams.MATCH_PARENT
24 | import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
25 | import androidx.recyclerview.widget.RecyclerView
26 | import androidx.recyclerview.widget.RecyclerView.LayoutParams
27 | import com.drakeet.multitype.ViewDelegate
28 | import com.drakeet.multitype.sample.dp
29 |
30 | /**
31 | * @author Drakeet Xu
32 | */
33 | class RichViewDelegate : ViewDelegate() {
34 |
35 | override fun onCreateView(context: Context): RichView {
36 | return RichView(context).apply { layoutParams = LayoutParams(MATCH_PARENT, WRAP_CONTENT) }
37 | }
38 |
39 | @SuppressLint("SetTextI18n")
40 | override fun onBindView(view: RichView, item: RichItem) {
41 | view.imageView.setImageResource(item.imageResId)
42 | view.textView.text = """
43 | |${item.text}
44 | |layoutPosition: ${view.layoutPosition}
45 | |absoluteAdapterPosition: ${view.absoluteAdapterPosition}
46 | |bindingAdapterPosition: ${view.bindingAdapterPosition}
47 | """.trimMargin()
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/payload/TestPayloadActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.payload
18 |
19 | import android.os.Bundle
20 | import android.widget.Toast
21 | import androidx.recyclerview.widget.DividerItemDecoration
22 | import androidx.recyclerview.widget.DividerItemDecoration.VERTICAL
23 | import androidx.recyclerview.widget.RecyclerView
24 | import com.drakeet.multitype.MultiTypeAdapter
25 | import com.drakeet.multitype.sample.MenuBaseActivity
26 | import com.drakeet.multitype.sample.R
27 | import java.util.*
28 |
29 | class TestPayloadActivity : MenuBaseActivity() {
30 |
31 | override fun onCreate(savedInstanceState: Bundle?) {
32 | super.onCreate(savedInstanceState)
33 | setContentView(R.layout.activity_list)
34 | val recyclerView = findViewById(R.id.list)
35 | recyclerView.addItemDecoration(DividerItemDecoration(this, VERTICAL))
36 | val adapter = MultiTypeAdapter()
37 | recyclerView.adapter = adapter
38 |
39 | adapter.register(HeavyItemViewBinder())
40 |
41 | val items = ArrayList()
42 | for (i in 0..29) {
43 | items.add(HeavyItem("1000$i"))
44 | }
45 | adapter.items = items
46 | adapter.notifyDataSetChanged()
47 |
48 | Toast.makeText(this, "Try to click or long click items", Toast.LENGTH_SHORT).show()
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/library/src/main/kotlin/com/drakeet/multitype/OneToManyBuilder.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype
18 |
19 | import androidx.annotation.CheckResult
20 |
21 | /**
22 | * @author Drakeet Xu
23 | */
24 | internal class OneToManyBuilder(
25 | private val adapter: MultiTypeAdapter,
26 | private val clazz: Class
27 | ) : OneToManyFlow, OneToManyEndpoint {
28 |
29 | private var delegates: Array>? = null
30 |
31 | @SafeVarargs
32 | @CheckResult(suggest = "#withLinker(Linker)")
33 | override fun to(vararg delegates: ItemViewDelegate) = apply {
34 | @Suppress("UNCHECKED_CAST")
35 | this.delegates = delegates as Array>
36 | }
37 |
38 | @SafeVarargs
39 | @CheckResult(suggest = "#withLinker(Linker)")
40 | override fun to(vararg binders: ItemViewBinder) = apply {
41 | @Suppress("UNCHECKED_CAST")
42 | this.delegates = binders as Array>
43 | }
44 |
45 | override fun withLinker(linker: Linker) {
46 | doRegister(linker)
47 | }
48 |
49 | override fun withJavaClassLinker(javaClassLinker: JavaClassLinker) {
50 | withLinker(ClassLinkerBridge.toLinker(javaClassLinker, delegates!!))
51 | }
52 |
53 | private fun doRegister(linker: Linker) {
54 | for (delegate in delegates!!) {
55 | adapter.register(Type(clazz, delegate, linker))
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/weibo/content/SimpleImageViewBinder.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.weibo.content
18 |
19 | import android.util.Log
20 | import android.view.LayoutInflater
21 | import android.view.View
22 | import android.view.ViewGroup
23 | import android.widget.ImageView
24 | import com.drakeet.multitype.sample.R
25 | import com.drakeet.multitype.sample.weibo.ContentHolder
26 | import com.drakeet.multitype.sample.weibo.WeiboFrameBinder
27 |
28 | /**
29 | * @author Drakeet Xu
30 | */
31 | class SimpleImageViewBinder : WeiboFrameBinder() {
32 |
33 | override fun onCreateContentViewHolder(inflater: LayoutInflater, parent: ViewGroup): ContentHolder {
34 | return ViewHolder(inflater.inflate(R.layout.item_weibo_simple_image, parent, false))
35 | }
36 |
37 | override fun onBindContentViewHolder(holder: ViewHolder, content: SimpleImage) {
38 | Log.d("weibo", "absoluteAdapterPosition: " + holder.absoluteAdapterPosition)
39 | Log.d("weibo", "getLayoutPosition: " + holder.layoutPosition)
40 | Log.d("weibo", "getOldPosition: " + holder.oldPosition)
41 | Log.d("weibo", "isRecyclable: " + holder.isRecyclable)
42 | holder.simpleImage.setImageResource(content.resId)
43 | }
44 |
45 | class ViewHolder(itemView: View) : ContentHolder(itemView) {
46 | val simpleImage: ImageView = itemView.findViewById(R.id.simple_image)
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/sample/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
21 |
22 |
29 |
30 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/library/src/main/kotlin/com/drakeet/multitype/Types.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype
18 |
19 | /**
20 | * An ordered collection to hold the types, delegates and linkers.
21 | *
22 | * @author Drakeet Xu
23 | */
24 | interface Types {
25 |
26 | /**
27 | * Returns the size of the [Types].
28 | */
29 | val size: Int
30 |
31 | fun register(type: Type)
32 |
33 | /**
34 | * Unregister all types indexed by the specified class.
35 | *
36 | * @param clazz the main class of a [Type]
37 | * @return true if any types are unregistered from this [Types]
38 | */
39 | fun unregister(clazz: Class<*>): Boolean
40 |
41 | /**
42 | * Gets the type at the specified index.
43 | *
44 | * @param index the type index
45 | * @return the [Type] at the specified index
46 | * @throws IndexOutOfBoundsException if the index is out of range
47 | */
48 | fun getType(index: Int): Type
49 |
50 | /**
51 | * For getting index of the type class. If the subclass is already registered,
52 | * the registered mapping is used. If the subclass is not registered, then look
53 | * for its parent class if is registered, if the parent class is registered,
54 | * the subclass is regarded as the parent class.
55 | *
56 | * @param clazz the type class.
57 | * @return The index of the first occurrence of the specified class in this [Types],
58 | * or -1 if this [Types] does not contain the class.
59 | */
60 | fun firstIndexOf(clazz: Class<*>): Int
61 | }
62 |
--------------------------------------------------------------------------------
/library/src/test/kotlin/com/drakeet/multitype/ItemViewDelegateTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype
18 |
19 | import com.google.common.truth.Truth.assertThat
20 | import org.junit.Test
21 |
22 | /**
23 | * @author Drakeet Xu
24 | */
25 | class ItemViewDelegateTest {
26 |
27 | @Test
28 | fun shouldGetNonNullAdapter() {
29 | var exception: Exception? = null
30 | val adapter = MultiTypeAdapter()
31 | val empty = arrayListOf()
32 | adapter.items = empty
33 |
34 | val delegate = TestItemViewDelegate()
35 | adapter.register(TestItem::class.java, delegate)
36 |
37 | empty.add(TestItem("ItemViewDelegateTest"))
38 | try {
39 | delegate.notifyTestItemAdded()
40 | } catch (e: Exception) {
41 | e.printStackTrace()
42 | exception = e
43 | }
44 |
45 | assertThat(exception).isNull()
46 | }
47 |
48 | @Test(expected = IllegalStateException::class)
49 | fun shouldThrowIllegalStateException() {
50 | val adapter = MultiTypeAdapter()
51 | val empty = ArrayList()
52 | adapter.items = empty
53 |
54 | val delegate = TestItemViewDelegate()
55 |
56 | empty.add(TestItem("ItemViewDelegateTest"))
57 | delegate.notifyTestItemAdded()
58 |
59 | adapter.register(delegate)
60 | }
61 |
62 | class TestItemViewDelegate : com.drakeet.multitype.TestItemViewDelegate() {
63 | fun notifyTestItemAdded() {
64 | assertThat(adapter).isNotNull()
65 | assertThat(adapter.toString()).isNotNull()
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/library/src/main/kotlin/com/drakeet/multitype/ViewDelegate.kt:
--------------------------------------------------------------------------------
1 | package com.drakeet.multitype
2 |
3 | import android.content.Context
4 | import android.view.View
5 | import android.view.ViewGroup
6 | import androidx.recyclerview.widget.RecyclerView
7 |
8 | /**
9 | * This is a simple [ItemViewDelegate] that does not require to declare and provide a [RecyclerView.ViewHolder].
10 | * @since v4.2.0
11 | * @author Drakeet Xu
12 | */
13 | abstract class ViewDelegate : ItemViewDelegate>() {
14 |
15 | protected val View.holder: Holder get() {
16 | return holder(this) ?: throw IllegalAccessException("The view holder property can only be called after onCreateView()!")
17 | }
18 |
19 | protected val View.layoutPosition: Int get() = holder.layoutPosition
20 |
21 | protected val View.absoluteAdapterPosition: Int get() = holder.absoluteAdapterPosition
22 |
23 | protected val View.bindingAdapterPosition: Int get() = holder.bindingAdapterPosition
24 |
25 | abstract fun onCreateView(context: Context): V
26 |
27 | abstract fun onBindView(view: V, item: T)
28 |
29 | // Override this function if you need a parent ViewGroup
30 | open fun onCreateView(context: Context, parent: ViewGroup): V {
31 | return onCreateView(context)
32 | }
33 |
34 | // Override this function if you need a ViewHolder or positions
35 | open fun onBindView(holder: Holder, view: V, item: T) {
36 | view.setTag(R.id.tagViewHolder, holder)
37 | onBindView(view, item)
38 | }
39 |
40 | protected fun getRecyclerLayoutParams(view: View): RecyclerView.LayoutParams {
41 | return (view.layoutParams as RecyclerView.LayoutParams)
42 | }
43 |
44 | private fun holder(view: View): Holder? {
45 | @Suppress("UNCHECKED_CAST")
46 | return view.getTag(R.id.tagViewHolder) as? Holder
47 | }
48 |
49 | override fun onCreateViewHolder(context: Context, parent: ViewGroup): Holder {
50 | return Holder(onCreateView(context, parent))
51 | }
52 |
53 | override fun onBindViewHolder(holder: Holder, item: T) = onBindView(holder, holder.view, item)
54 |
55 | class Holder(val view: V) : RecyclerView.ViewHolder(view)
56 | }
57 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_weibo_frame.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
22 |
23 |
27 |
28 |
34 |
35 |
42 |
43 |
49 |
50 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/bilibili/PostsAdapter.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.bilibili
18 |
19 | import android.view.LayoutInflater
20 | import android.view.View
21 | import android.view.ViewGroup
22 | import android.widget.ImageView
23 | import android.widget.TextView
24 | import android.widget.Toast
25 | import androidx.recyclerview.widget.RecyclerView
26 | import com.drakeet.multitype.sample.R
27 |
28 | /**
29 | * @author Drakeet Xu
30 | */
31 | class PostsAdapter : RecyclerView.Adapter() {
32 |
33 | private var posts = emptyList()
34 |
35 | fun setPosts(posts: List) {
36 | this.posts = posts
37 | }
38 |
39 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
40 | return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_horizontal_post, parent, false))
41 | }
42 |
43 | override fun onBindViewHolder(holder: ViewHolder, position: Int) {
44 | val post = posts[position]
45 | holder.cover.setImageResource(post.coverResId)
46 | holder.title.text = post.title
47 | }
48 |
49 | override fun getItemCount(): Int {
50 | return posts.size
51 | }
52 |
53 | class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
54 |
55 | var cover: ImageView = itemView.findViewById(R.id.cover)
56 | var title: TextView = itemView.findViewById(R.id.title)
57 |
58 | init {
59 | itemView.setOnClickListener { v -> Toast.makeText(v.context, absoluteAdapterPosition.toString(), Toast.LENGTH_SHORT).show() }
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/selectable/SquareViewBinder.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.selectable
18 |
19 | import android.view.LayoutInflater
20 | import android.view.View
21 | import android.view.ViewGroup
22 | import android.widget.TextView
23 | import androidx.recyclerview.widget.RecyclerView
24 | import com.drakeet.multitype.ItemViewBinder
25 | import com.drakeet.multitype.sample.R
26 |
27 | /**
28 | * @author Drakeet Xu
29 | */
30 | class SquareViewBinder(val selectedSet: MutableSet) : ItemViewBinder() {
31 |
32 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): ViewHolder {
33 | return ViewHolder(inflater.inflate(R.layout.item_square, parent, false))
34 | }
35 |
36 | override fun onBindViewHolder(holder: ViewHolder, item: Square) {
37 | holder.square = item
38 | holder.squareView.text = item.number.toString()
39 | holder.squareView.isSelected = item.isSelected
40 | }
41 |
42 | inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
43 |
44 | val squareView: TextView = itemView.findViewById(R.id.square)
45 | lateinit var square: Square
46 |
47 | init {
48 | itemView.setOnClickListener {
49 | square.apply {
50 | squareView.isSelected = !isSelected
51 | this.isSelected = !isSelected
52 | }
53 | if (square.isSelected) {
54 | selectedSet.add(square.number)
55 | } else {
56 | selectedSet.remove(square.number)
57 | }
58 | }
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/sample/src/androidTest/kotlin/com/drakeet/multitype/sample/SmokeTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample
18 |
19 | import android.view.View
20 | import androidx.test.InstrumentationRegistry.getInstrumentation
21 | import androidx.test.espresso.Espresso
22 | import androidx.test.espresso.Espresso.onView
23 | import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
24 | import androidx.test.espresso.action.ViewActions.click
25 | import androidx.test.espresso.matcher.ViewMatchers.*
26 | import androidx.test.filters.LargeTest
27 | import androidx.test.rule.ActivityTestRule
28 | import androidx.test.runner.AndroidJUnit4
29 | import com.drakeet.multitype.sample.bilibili.BilibiliActivity
30 | import org.hamcrest.Matchers.allOf
31 | import org.junit.Rule
32 | import org.junit.Test
33 | import org.junit.runner.RunWith
34 |
35 | /**
36 | * @author Drakeet Xu
37 | */
38 | @LargeTest
39 | @RunWith(AndroidJUnit4::class)
40 | class SmokeTest {
41 |
42 | @get:Rule
43 | var rule = ActivityTestRule(BilibiliActivity::class.java)
44 |
45 | private val menus = arrayOf(
46 | "NormalActivity",
47 | "MultiSelectableActivity",
48 | "communicate with binder",
49 | "BilibiliActivity",
50 | "WeiboActivity",
51 | "OneDataToManyActivity",
52 | "TestPayloadActivity",
53 | "MoreApisPlayground"
54 | )
55 |
56 | @Test
57 | fun smokeTest() {
58 | Espresso.closeSoftKeyboard()
59 | menus.forEach {
60 | openActionBarOverflowOrOptionsMenu(getInstrumentation().targetContext)
61 | onView(allOf(withId(R.id.title), withText(it), isDisplayed())).perform(click())
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/communication/TextItemWithOutsizeDataViewBinder.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.communication
18 |
19 | import android.view.LayoutInflater
20 | import android.view.View
21 | import android.view.ViewGroup
22 | import android.widget.TextView
23 | import android.widget.Toast
24 | import androidx.recyclerview.widget.RecyclerView
25 | import com.drakeet.multitype.ItemViewBinder
26 | import com.drakeet.multitype.sample.R
27 | import com.drakeet.multitype.sample.normal.TextItem
28 |
29 | /**
30 | * @author Drakeet Xu
31 | */
32 | class TextItemWithOutsizeDataViewBinder(var aValueFromOutside: String) : ItemViewBinder() {
33 |
34 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): ViewHolder {
35 | return ViewHolder(inflater.inflate(R.layout.item_text, parent, false))
36 | }
37 |
38 | override fun onBindViewHolder(holder: ViewHolder, item: TextItem) {
39 | holder.setData(item)
40 | }
41 |
42 | inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
43 |
44 | private var textView: TextView = itemView.findViewById(R.id.text)
45 | private lateinit var value: String
46 |
47 | init {
48 | textView.setOnClickListener { v ->
49 | Toast.makeText(
50 | v.context,
51 | "item's value: $value, aValueFromOutside: $aValueFromOutside", Toast.LENGTH_SHORT
52 | ).show()
53 | }
54 | }
55 |
56 | fun setData(textItem: TextItem) {
57 | textView.text = textItem.text
58 | this.value = textItem.text
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/library/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | apply plugin: 'com.android.library'
18 | apply plugin: 'kotlin-android'
19 | apply plugin: 'org.jetbrains.dokka-android'
20 | apply plugin: 'jacoco'
21 | apply from: rootProject.file('gradle/publish-docs.gradle')
22 | apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
23 |
24 | android {
25 | compileSdkVersion buildConfig.compileSdkVersion
26 |
27 | defaultConfig {
28 | minSdkVersion buildConfig.minSdkVersion
29 | }
30 |
31 | compileOptions {
32 | kotlinOptions.freeCompilerArgs += ['-module-name', "multitype"]
33 | }
34 |
35 | // TODO replace with https://issuetracker.google.com/issues/72050365 once released.
36 | libraryVariants.all { variant ->
37 | variant.generateBuildConfigProvider.configure {
38 | it.enabled = false
39 | }
40 | }
41 |
42 | testOptions {
43 | unitTests {
44 | includeAndroidResources = true
45 | }
46 | }
47 |
48 | sourceSets {
49 | main.java.srcDirs += 'src/main/kotlin'
50 | test.java.srcDirs += 'src/test/kotlin'
51 | }
52 | }
53 |
54 | dependencies {
55 | testImplementation 'junit:junit:4.13'
56 | testImplementation "org.robolectric:robolectric:4.3.1"
57 | testImplementation "org.mockito:mockito-inline:2.18.0"
58 | testImplementation "androidx.recyclerview:recyclerview:$recyclerviewVersion"
59 | testImplementation "com.google.truth:truth:1.0"
60 | testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0"
61 |
62 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
63 | api "androidx.annotation:annotation:$annotationVersion"
64 | api "androidx.recyclerview:recyclerview:$recyclerviewVersion"
65 | }
66 |
--------------------------------------------------------------------------------
/sample/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | apply plugin: 'com.android.application'
18 | apply plugin: 'kotlin-android'
19 | apply plugin: 'kotlin-android-extensions'
20 |
21 | android {
22 | compileSdkVersion buildConfig.compileSdkVersion
23 |
24 | defaultConfig {
25 | applicationId "me.drakeet.multitype.sample"
26 | minSdkVersion buildConfig.minSdkVersion
27 | targetSdkVersion buildConfig.targetSdkVersion
28 | versionCode buildConfig.versionCode
29 | versionName buildConfig.versionName
30 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
31 | }
32 |
33 | buildTypes {
34 | release {
35 | minifyEnabled false
36 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
37 | }
38 | }
39 |
40 | compileOptions {
41 | sourceCompatibility JavaVersion.VERSION_1_8
42 | targetCompatibility JavaVersion.VERSION_1_8
43 | }
44 |
45 | sourceSets {
46 | main.java.srcDirs += 'src/main/kotlin'
47 | androidTest.java.srcDirs += 'src/androidTest/kotlin'
48 | }
49 | }
50 |
51 | dependencies {
52 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
53 | implementation project(':library')
54 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
55 | androidTestImplementation 'androidx.test:rules:1.3.0'
56 | androidTestImplementation "androidx.annotation:annotation:$annotationVersion"
57 | androidTestImplementation "com.google.truth:truth:1.0"
58 | implementation "androidx.appcompat:appcompat:$appcompatVersion"
59 | implementation "androidx.recyclerview:recyclerview:$recyclerviewVersion"
60 | implementation 'com.google.code.gson:gson:2.8.6'
61 | }
62 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/bilibili/HorizontalPostsHolderInflater.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.bilibili
18 |
19 | import android.view.LayoutInflater
20 | import android.view.View
21 | import android.view.ViewGroup
22 | import androidx.recyclerview.widget.LinearLayoutManager
23 | import androidx.recyclerview.widget.LinearSnapHelper
24 | import androidx.recyclerview.widget.RecyclerView
25 | import com.drakeet.multitype.ViewHolderInflater
26 | import com.drakeet.multitype.sample.R
27 |
28 | /**
29 | * @author Drakeet Xu
30 | */
31 | class HorizontalPostsHolderInflater : ViewHolderInflater() {
32 |
33 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): ViewHolder {
34 | return ViewHolder(inflater.inflate(R.layout.item_horizontal_list, parent, false))
35 | }
36 |
37 | override fun onBindViewHolder(holder: ViewHolder, item: PostList) {
38 | holder.setPosts(item.posts)
39 | }
40 |
41 | class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
42 |
43 | private val adapter: PostsAdapter = PostsAdapter()
44 | private val recyclerView: RecyclerView = itemView.findViewById(R.id.post_list)
45 |
46 | init {
47 | val layoutManager = LinearLayoutManager(itemView.context)
48 | layoutManager.orientation = LinearLayoutManager.HORIZONTAL
49 | recyclerView.layoutManager = layoutManager
50 | LinearSnapHelper().attachToRecyclerView(recyclerView)
51 | recyclerView.adapter = adapter
52 | }
53 |
54 | fun setPosts(posts: List) {
55 | adapter.setPosts(posts)
56 | adapter.notifyDataSetChanged()
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/library/src/main/kotlin/com/drakeet/multitype/OneToManyEndpoint.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype
18 |
19 | import kotlin.reflect.KClass
20 |
21 | /**
22 | * End-operators for one-to-many.
23 | *
24 | * @author Drakeet Xu
25 | */
26 | interface OneToManyEndpoint {
27 |
28 | /**
29 | * Sets a linker to link the items and delegates by array index.
30 | *
31 | * @param linker the row linker
32 | * @see Linker
33 | */
34 | fun withLinker(linker: Linker)
35 |
36 | fun withLinker(linker: (position: Int, item: T) -> Int) {
37 | withLinker(object : Linker {
38 | override fun index(position: Int, item: T): Int {
39 | return linker(position, item)
40 | }
41 | })
42 | }
43 |
44 | /**
45 | * Sets a class linker to link the items and delegates by the class instance of delegates.
46 | *
47 | * @param javaClassLinker the class linker
48 | * @see JavaClassLinker
49 | */
50 | fun withJavaClassLinker(javaClassLinker: JavaClassLinker)
51 |
52 | private fun withJavaClassLinker(classLinker: (position: Int, item: T) -> Class>) {
53 | withJavaClassLinker(object : JavaClassLinker {
54 | override fun index(position: Int, item: T): Class> {
55 | return classLinker(position, item)
56 | }
57 | })
58 | }
59 |
60 | fun withKotlinClassLinker(classLinker: KotlinClassLinker) {
61 | withJavaClassLinker { position, item -> classLinker.index(position, item).java }
62 | }
63 |
64 | fun withKotlinClassLinker(classLinker: (position: Int, item: T) -> KClass>) {
65 | withJavaClassLinker { position, item -> classLinker(position, item).java }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/one2many/OneDataToManyActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.one2many
18 |
19 | import android.os.Bundle
20 | import androidx.annotation.VisibleForTesting
21 | import androidx.recyclerview.widget.RecyclerView
22 | import com.drakeet.multitype.MultiTypeAdapter
23 | import com.drakeet.multitype.sample.MenuBaseActivity
24 | import com.drakeet.multitype.sample.R
25 | import java.util.*
26 |
27 | /**
28 | * @author Drakeet Xu
29 | */
30 | class OneDataToManyActivity : MenuBaseActivity() {
31 |
32 | @VisibleForTesting
33 | lateinit var recyclerView: RecyclerView
34 | @VisibleForTesting
35 | lateinit var adapter: MultiTypeAdapter
36 |
37 | private val dataFromService: List
38 | @VisibleForTesting
39 | get() {
40 | val list = ArrayList()
41 | var i = 0
42 | while (i < 30) {
43 | list.add(Data("title: $i", Data.TYPE_1))
44 | list.add(Data("title: ${ i + 1 }", Data.TYPE_2))
45 | i += 2
46 | }
47 | return list
48 | }
49 |
50 | override fun onCreate(savedInstanceState: Bundle?) {
51 | super.onCreate(savedInstanceState)
52 | setContentView(R.layout.activity_list)
53 | recyclerView = findViewById(R.id.list)
54 | adapter = MultiTypeAdapter()
55 |
56 | adapter.register(Data::class).to(
57 | DataType1ViewBinder(),
58 | DataType2ViewBinder()
59 | ).withKotlinClassLinker { _, data ->
60 | when (data.type) {
61 | Data.TYPE_2 -> DataType2ViewBinder::class
62 | else -> DataType1ViewBinder::class
63 | }
64 | }
65 |
66 | adapter.items = dataFromService
67 | adapter.notifyDataSetChanged()
68 | recyclerView.adapter = adapter
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/normal/TextItemViewBinder.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.normal
18 |
19 | import android.annotation.SuppressLint
20 | import android.view.LayoutInflater
21 | import android.view.View
22 | import android.view.ViewGroup
23 | import android.view.animation.AnimationUtils
24 | import android.widget.TextView
25 | import androidx.recyclerview.widget.RecyclerView
26 | import com.drakeet.multitype.ItemViewBinder
27 | import com.drakeet.multitype.sample.R
28 |
29 | /**
30 | * @author Drakeet Xu
31 | */
32 | class TextItemViewBinder : ItemViewBinder() {
33 |
34 | private var lastShownAnimationPosition: Int = 0
35 |
36 | class TextHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
37 | val text: TextView = itemView.findViewById(R.id.text)
38 | }
39 |
40 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): TextHolder {
41 | return TextHolder(inflater.inflate(R.layout.item_text, parent, false))
42 | }
43 |
44 | @SuppressLint("SetTextI18n")
45 | override fun onBindViewHolder(holder: TextHolder, item: TextItem) {
46 | holder.text.text = "hello: " + item.text
47 | // should show animation, ref: https://github.com/drakeet/MultiType/issues/149
48 | setAnimation(holder.itemView, holder.absoluteAdapterPosition)
49 | }
50 |
51 | private fun setAnimation(viewToAnimate: View, position: Int) {
52 | if (position > lastShownAnimationPosition) {
53 | viewToAnimate.startAnimation(AnimationUtils.loadAnimation(viewToAnimate.context, android.R.anim.slide_in_left))
54 | lastShownAnimationPosition = position
55 | }
56 | }
57 |
58 | override fun onViewDetachedFromWindow(holder: TextHolder) {
59 | holder.itemView.clearAnimation()
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/sample/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
72 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # MultiType Releases
2 |
3 | ### Version 4.2.0 - Dec 24, 2019
4 |
5 | - Add `ViewDelegate` that does not require `ViewHolder` (#296)
6 |
7 | ### Version 4.1.1 - Dec 11, 2019
8 |
9 | - Fix binary incompatibility about `ItemViewBinder` (#294)
10 |
11 | ### Version 4.1.0 - Dec 9, 2019
12 |
13 | - Add `ItemViewDelegate` & `onCreateViewHolder(context, _)` (#292)
14 | - Kotlin 1.3.61
15 |
16 | ### Version 4.0.0 - Sep 7, 2019
17 |
18 | - Migrate to com.drakeet group (#267)
19 | - Kotlin 1.3.50
20 | - AndroidX Annotation 1.1.0
21 | - Fix duplicate library_release.kotlin_module (#284)
22 |
23 | ### Version 4.0.0-alpha3 - Mar 16, 2019
24 |
25 | - Change `TypePool` to `Types`
26 | - Rename `ArrayTypePool` to `MutableTypes`
27 | - Open `MultiTypeAdapter` & `MutableTypes`
28 |
29 | ### Version 4.0.0-alpha2 - Feb 06, 2019
30 |
31 | This migrates MultiType to Kotlin ([#253](https://github.com/drakeet/MultiType/pull/253))
32 |
33 | #### Features
34 |
35 | - Add a new reified `MultiTypeAdapter#register(ItemViewBinder)`
36 | - Add a new class `Type` for `TypePool` to hold data
37 | - Add `withKotlinClassLinker` for `OneToManyEndpoint`
38 | - Add `ItemViewBinder#adapterItems` to get or set the items of the associated `MultiTypeAdapter`
39 | - Change `MultiTypeAdapter#items` from `List<*>` to `List`
40 |
41 | #### Breaking Changes
42 |
43 | - Change all protected methods of `ItemViewBinder` to public ([#245](https://github.com/drakeet/MultiType/issues/245))
44 | - Change the `payloads` parameter of `ItemViewBinder#onBindViewHolder(holder, item, payloads)` to be of `List` type
45 | - Change the `clazz` parameter of `MultiTypeAdapter#register(...)` from `Class extends T>` to `Class`
46 | - ~~Change `MultiTypeAdapter` to `final`~~
47 | - Remove `Items` class
48 | - Remove `Preconditions` class
49 | - Rename `MultiTypePool` to `ArrayTypePool`
50 | - Rename `KClassLinker` to `KotlinClassLinker`
51 | - Rename `ClassLinker` to `JavaClassLinker`
52 | - Rename `OneToManyEndpoint#withKClassLinker(...)` method to `withKotlinClassLinker`
53 | - Rename `OneToManyEndpoint#withClassLinker(...)` method to `withJavaClassLinker`
54 |
55 | ### Version 3.5.0 - Sep 22, 2018
56 |
57 | - Migrate to AndroidX
58 | - Rename Kotlin extension artifact to -ktx
59 |
60 | ### Version 3.4.4 - Feb 17, 2018
61 |
62 | Some minor changes:
63 | - Disable `BuildConfig` generation
64 | - Change some dependencies of libraries from `implementation` to `api`
65 | - Improve the tip of `BinderNotFoundException`
66 |
--------------------------------------------------------------------------------
/library/src/test/kotlin/com/drakeet/multitype/MultiTypeTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype
18 |
19 | import com.google.common.truth.Truth.assertThat
20 | import org.junit.Test
21 | import org.junit.runner.RunWith
22 | import org.junit.runners.JUnit4
23 |
24 | /**
25 | * @author Drakeet Xu
26 | */
27 | @RunWith(JUnit4::class)
28 | class MultiTypeTest {
29 |
30 | private val adapter = MultiTypeAdapter()
31 | private val simpleLinker = object : Linker {
32 | override fun index(position: Int, item: String): Int = 0
33 | }
34 |
35 | @Test
36 | fun shouldEqualToRegisteredKClass() {
37 | adapter.register(String::class, StringViewDelegate())
38 | assertThat(adapter.types.getType(0).clazz).isEqualTo(String::class.java)
39 | }
40 |
41 | @Test
42 | fun shouldEqualToRegisteredKClass_Reified() {
43 | adapter.register(StringViewDelegate())
44 | assertThat(adapter.types.getType(0).clazz).isEqualTo(String::class.java)
45 | }
46 |
47 | @Test
48 | fun shouldEqualToRegisteredOneToManyKClass() {
49 | adapter.register(String::class)
50 | .to(StringViewDelegate())
51 | .withLinker(simpleLinker)
52 | assertThat(adapter.types.getType(0).clazz).isEqualTo(String::class.java)
53 | }
54 |
55 | @Test
56 | fun shouldEqualToRegisteredKClass_TypePool() {
57 | adapter.types.register(Type(String::class.java, StringViewDelegate(), simpleLinker))
58 | assertThat(adapter.types.getType(0).clazz).isEqualTo(String::class.java)
59 | }
60 |
61 | @Test
62 | fun shouldUnregisterKClass_TypePool() {
63 | adapter.types.register(Type(String::class.java, StringViewDelegate(), simpleLinker))
64 | assertThat(adapter.types.unregister(String::class.java)).isTrue()
65 | }
66 |
67 | @Test
68 | fun shouldEqualToRegisteredFirstKClass_TypePool() {
69 | adapter.types.register(Type(String::class.java, StringViewDelegate(), simpleLinker))
70 | assertThat(adapter.types.firstIndexOf(String::class.java)).isEqualTo(0)
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/normal/NormalActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.normal
18 |
19 | import android.annotation.SuppressLint
20 | import android.content.Context
21 | import android.os.Bundle
22 | import android.widget.TextView
23 | import androidx.recyclerview.widget.RecyclerView
24 | import com.drakeet.multitype.MultiTypeAdapter
25 | import com.drakeet.multitype.ViewDelegate
26 | import com.drakeet.multitype.sample.MenuBaseActivity
27 | import com.drakeet.multitype.sample.R
28 | import java.util.*
29 |
30 | /**
31 | * @author Drakeet Xu
32 | */
33 | class NormalActivity : MenuBaseActivity() {
34 |
35 | private val adapter = MultiTypeAdapter()
36 | private val items = ArrayList()
37 |
38 | override fun onCreate(savedInstanceState: Bundle?) {
39 | super.onCreate(savedInstanceState)
40 | setContentView(R.layout.activity_list)
41 | val recyclerView = findViewById(R.id.list)
42 |
43 | adapter.register(TextItemViewBinder())
44 | adapter.register(ImageItemViewBinder())
45 | // ✨✨✨
46 | adapter.register(RichViewDelegate())
47 |
48 | // Test https://github.com/drakeet/MultiType/issues/302
49 | // Kotlin will reify and inline this to Integer.class
50 | adapter.register(Int::class, IntViewDelegate())
51 |
52 | recyclerView.adapter = adapter
53 |
54 | val textItem = TextItem("world")
55 | val imageItem = ImageItem(R.mipmap.ic_launcher)
56 | val richItem = RichItem("小艾大人赛高", R.drawable.img_11)
57 |
58 | for (i in 0..19) {
59 | items.add(textItem)
60 | items.add(imageItem)
61 | items.add(richItem)
62 | }
63 | items.add(Integer.valueOf(999))
64 | items.add(666)
65 | items.add(333)
66 | adapter.items = items
67 | adapter.notifyDataSetChanged()
68 | }
69 |
70 | private class IntViewDelegate : ViewDelegate() {
71 |
72 | override fun onCreateView(context: Context): TextView {
73 | return TextView(context)
74 | }
75 |
76 | @SuppressLint("SetTextI18n")
77 | override fun onBindView(view: TextView, item: Int) {
78 | view.text = "IntViewItem: $item"
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/MenuBaseActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample
18 |
19 | import android.annotation.SuppressLint
20 | import android.content.Intent
21 | import android.view.Menu
22 | import android.view.MenuItem
23 | import androidx.appcompat.app.AppCompatActivity
24 | import com.drakeet.multitype.sample.bilibili.BilibiliActivity
25 | import com.drakeet.multitype.sample.communication.CommunicateWithBinderActivity
26 | import com.drakeet.multitype.sample.more.MoreApisPlayground
27 | import com.drakeet.multitype.sample.normal.NormalActivity
28 | import com.drakeet.multitype.sample.one2many.OneDataToManyActivity
29 | import com.drakeet.multitype.sample.payload.TestPayloadActivity
30 | import com.drakeet.multitype.sample.selectable.MultiSelectableActivity
31 | import com.drakeet.multitype.sample.weibo.WeiboActivity
32 |
33 | /**
34 | * @author Drakeet Xu
35 | */
36 | @SuppressLint("Registered")
37 | open class MenuBaseActivity : AppCompatActivity() {
38 |
39 | override fun onCreateOptionsMenu(menu: Menu): Boolean {
40 | super.onCreateOptionsMenu(menu)
41 | menuInflater.inflate(R.menu.menu_main, menu)
42 | return true
43 | }
44 |
45 | override fun onOptionsItemSelected(item: MenuItem): Boolean {
46 | val intent = Intent()
47 | when (item.itemId) {
48 | R.id.NormalActivity -> intent.setClass(this, NormalActivity::class.java)
49 | R.id.MultiSelectableActivity -> intent.setClass(this, MultiSelectableActivity::class.java)
50 | R.id.CommunicateWithBinderActivity -> intent.setClass(this, CommunicateWithBinderActivity::class.java)
51 | R.id.BilibiliActivity -> intent.setClass(this, BilibiliActivity::class.java)
52 | R.id.WeiboActivity -> intent.setClass(this, WeiboActivity::class.java)
53 | R.id.OneDataToManyActivity -> intent.setClass(this, OneDataToManyActivity::class.java)
54 | R.id.TestPayloadActivity -> intent.setClass(this, TestPayloadActivity::class.java)
55 | R.id.MoreApisPlayground -> intent.setClass(this, MoreApisPlayground::class.java)
56 | else -> return false
57 | }
58 | startActivity(intent)
59 | this.finish()
60 | return true
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/sample/src/androidTest/kotlin/com/drakeet/multitype/sample/one2many/OneToManyTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.one2many
18 |
19 | import android.os.SystemClock
20 | import androidx.test.espresso.Espresso.onView
21 | import androidx.test.espresso.assertion.ViewAssertions.matches
22 | import androidx.test.espresso.matcher.ViewMatchers.withHint
23 | import androidx.test.rule.ActivityTestRule
24 | import androidx.test.runner.AndroidJUnit4
25 | import com.drakeet.multitype.MultiTypeAdapter
26 | import com.drakeet.multitype.sample.R
27 | import com.drakeet.multitype.sample.RecyclerViewMatcher.Companion.withRecyclerView
28 | import org.junit.Before
29 | import org.junit.Rule
30 | import org.junit.Test
31 | import org.junit.runner.RunWith
32 |
33 | /**
34 | * @author Drakeet Xu
35 | */
36 | @RunWith(AndroidJUnit4::class)
37 | class OneToManyTest {
38 |
39 | private val testTitle = "testTitle"
40 |
41 | private lateinit var items: List
42 | private lateinit var adapter: MultiTypeAdapter
43 |
44 | @get:Rule
45 | var rule = ActivityTestRule(
46 | OneDataToManyActivity::class.java
47 | )
48 |
49 | @Before
50 | fun setup() {
51 | items = rule.activity.adapter.items
52 | adapter = rule.activity.adapter
53 | }
54 |
55 | @Test
56 | @Throws(Throwable::class)
57 | fun shouldRefreshTypeChanged() {
58 | val originalFirst = items[0] as Data
59 | for (i in 0..1) {
60 | rule.runOnUiThread {
61 | originalFirst.type = Data.TYPE_2
62 | adapter.notifyItemChanged(0)
63 | }
64 | onView(
65 | withRecyclerView(R.id.list).atPositionOnView(0, android.R.id.title)
66 | )
67 | .check(matches(withHint("right")))
68 | SystemClock.sleep(2000)
69 | rule.runOnUiThread { rule.activity.recyclerView.smoothScrollToPosition(items.size - 1) }
70 | SystemClock.sleep(2000)
71 | rule.runOnUiThread {
72 | rule.activity.recyclerView.smoothScrollToPosition(0)
73 | originalFirst.type = Data.TYPE_1
74 | adapter.notifyItemChanged(0)
75 | }
76 | SystemClock.sleep(2000)
77 | onView(
78 | withRecyclerView(R.id.list).atPositionOnView(0, android.R.id.title)
79 | )
80 | .check(matches(withHint("left")))
81 | SystemClock.sleep(2000)
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/payload/HeavyItemViewBinder.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.payload
18 |
19 | import android.annotation.SuppressLint
20 | import android.view.LayoutInflater
21 | import android.view.View
22 | import android.view.ViewGroup
23 | import android.widget.TextView
24 | import android.widget.Toast
25 | import androidx.recyclerview.widget.RecyclerView
26 | import com.drakeet.multitype.ItemViewBinder
27 | import com.drakeet.multitype.sample.R
28 |
29 | /**
30 | * @author Drakeet Xu
31 | */
32 | internal class HeavyItemViewBinder : ItemViewBinder() {
33 |
34 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): ViewHolder {
35 | return ViewHolder(inflater.inflate(R.layout.item_heavy, parent, false))
36 | }
37 |
38 | @SuppressLint("SetTextI18n")
39 | override fun onBindViewHolder(holder: ViewHolder, item: HeavyItem) {
40 | holder.firstText.text = item.text
41 | holder.endText.text = "currentTimeMillis: " + System.currentTimeMillis()
42 | holder.item = item
43 | }
44 |
45 | @SuppressLint("SetTextI18n")
46 | override fun onBindViewHolder(holder: ViewHolder, item: HeavyItem, payloads: List) {
47 | if (payloads.isEmpty()) {
48 | super.onBindViewHolder(holder, item, payloads)
49 | } else {
50 | holder.firstText.text = "Just update the first text: " + payloads[0]
51 | }
52 | }
53 |
54 | inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener, View.OnLongClickListener {
55 |
56 | var firstText: TextView = itemView.findViewById(R.id.first_text)
57 | var endText: TextView = itemView.findViewById(R.id.end_text)
58 | var item: HeavyItem? = null
59 |
60 | init {
61 | itemView.setOnClickListener(this)
62 | itemView.setOnLongClickListener(this)
63 | }
64 |
65 | override fun onClick(v: View) {
66 | Toast.makeText(v.context, "Update with a payload", Toast.LENGTH_SHORT).show()
67 | adapter.notifyItemChanged(bindingAdapterPosition, "la la la (payload)")
68 | }
69 |
70 | override fun onLongClick(v: View): Boolean {
71 | Toast.makeText(v.context, "Full update", Toast.LENGTH_SHORT).show()
72 | item!!.text = "full full full"
73 | adapter.notifyItemChanged(bindingAdapterPosition)
74 | return true
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/activity_more_apis_playground.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
27 |
28 |
33 |
34 |
40 |
41 |
47 |
48 |
54 |
55 |
56 |
57 |
63 |
64 |
70 |
71 |
72 |
73 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/sample/src/androidTest/kotlin/com/drakeet/multitype/sample/RecyclerViewMatcher.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample
18 |
19 | import android.content.res.Resources
20 | import android.view.View
21 | import androidx.recyclerview.widget.RecyclerView
22 | import org.hamcrest.Description
23 | import org.hamcrest.Matcher
24 | import org.hamcrest.TypeSafeMatcher
25 |
26 | /**
27 | * @author dannyroa
28 | * @author Drakeet Xu
29 | */
30 | class RecyclerViewMatcher private constructor(private val recyclerViewId: Int) {
31 |
32 | fun atPosition(position: Int): Matcher {
33 | return atPositionOnView(position, -1)
34 | }
35 |
36 | fun atPositionOnView(position: Int, targetViewId: Int): Matcher {
37 |
38 | return object : TypeSafeMatcher() {
39 | var resources: Resources? = null
40 | var childView: View? = null
41 |
42 | override fun describeTo(description: Description) {
43 | var idDescription = Integer.toString(recyclerViewId)
44 | if (this.resources != null) {
45 | try {
46 | idDescription = this.resources!!.getResourceName(recyclerViewId)
47 | } catch (var4: Resources.NotFoundException) {
48 | idDescription = String.format(
49 | "%s (resource name not found)",
50 | recyclerViewId
51 | )
52 | }
53 |
54 | }
55 |
56 | description.appendText("with id: $idDescription")
57 | }
58 |
59 | public override fun matchesSafely(view: View): Boolean {
60 |
61 | this.resources = view.resources
62 |
63 | if (childView == null) {
64 | val recyclerView = view.rootView.findViewById(recyclerViewId)
65 | if (recyclerView != null && recyclerView.id == recyclerViewId) {
66 | childView = recyclerView.findViewHolderForAdapterPosition(
67 | position
68 | )!!.itemView
69 | } else {
70 | return false
71 | }
72 | }
73 |
74 | if (targetViewId == -1) {
75 | return view === childView
76 | } else {
77 | val targetView = childView!!.findViewById(targetViewId)
78 | return view === targetView
79 | }
80 | }
81 | }
82 | }
83 |
84 | companion object {
85 | fun withRecyclerView(recyclerViewId: Int): RecyclerViewMatcher {
86 | return RecyclerViewMatcher(recyclerViewId)
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/selectable/MultiSelectableActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.selectable
18 |
19 | import android.os.Bundle
20 | import android.widget.Button
21 | import android.widget.Toast
22 | import androidx.recyclerview.widget.GridLayoutManager
23 | import androidx.recyclerview.widget.RecyclerView
24 | import com.drakeet.multitype.MultiTypeAdapter
25 | import com.drakeet.multitype.sample.MenuBaseActivity
26 | import com.drakeet.multitype.sample.R
27 | import com.drakeet.multitype.sample.common.Category
28 | import com.drakeet.multitype.sample.common.CategoryHolderInflater
29 | import java.util.*
30 |
31 | class MultiSelectableActivity : MenuBaseActivity() {
32 |
33 | var items: MutableList = ArrayList()
34 | var adapter = MultiTypeAdapter()
35 | private lateinit var fab: Button
36 | private lateinit var selectedSet: TreeSet
37 |
38 | override fun onCreate(savedInstanceState: Bundle?) {
39 | super.onCreate(savedInstanceState)
40 | setContentView(R.layout.activity_multi_selectable)
41 | val recyclerView = findViewById(R.id.list)
42 | val layoutManager = GridLayoutManager(this, SPAN_COUNT)
43 | layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
44 | override fun getSpanSize(position: Int): Int {
45 | return if (items[position] is Category) SPAN_COUNT else 1
46 | }
47 | }
48 |
49 | selectedSet = TreeSet()
50 |
51 | recyclerView.layoutManager = layoutManager
52 | adapter.register(CategoryHolderInflater())
53 | adapter.register(SquareViewBinder(selectedSet))
54 |
55 | loadData()
56 | recyclerView.adapter = adapter
57 |
58 | setupFAB()
59 | }
60 |
61 | private fun loadData() {
62 | val spacialCategory = Category("特别篇")
63 | items.add(spacialCategory)
64 | for (i in 0..6) {
65 | items.add(Square(i + 1))
66 | }
67 | val currentCategory = Category("本篇")
68 | items.add(currentCategory)
69 | for (i in 0..999) {
70 | items.add(Square(i + 1))
71 | }
72 | adapter.items = items
73 | adapter.notifyDataSetChanged()
74 | }
75 |
76 | private fun setupFAB() {
77 | fab = findViewById(R.id.fab)
78 | fab.setOnClickListener { v ->
79 | val content = StringBuilder()
80 | for (number in selectedSet) {
81 | content.append(number).append(" ")
82 | }
83 | Toast.makeText(v.context, "Selected items: $content", Toast.LENGTH_SHORT).show()
84 | }
85 | }
86 |
87 | companion object {
88 | private const val SPAN_COUNT = 5
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/weibo/WeiboFrameBinder.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.weibo
18 |
19 | import android.view.LayoutInflater
20 | import android.view.View
21 | import android.view.ViewGroup
22 | import android.widget.FrameLayout
23 | import android.widget.ImageView
24 | import android.widget.TextView
25 | import android.widget.Toast
26 | import android.widget.Toast.LENGTH_SHORT
27 | import androidx.recyclerview.widget.RecyclerView
28 | import com.drakeet.multitype.ItemViewBinder
29 | import com.drakeet.multitype.sample.R
30 |
31 | /**
32 | * @author Drakeet Xu
33 | */
34 | abstract class WeiboFrameBinder : ItemViewBinder() {
35 |
36 | protected abstract fun onCreateContentViewHolder(inflater: LayoutInflater, parent: ViewGroup): ContentHolder
37 |
38 | protected abstract fun onBindContentViewHolder(holder: SubViewHolder, content: Content)
39 |
40 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): FrameHolder {
41 | val root = inflater.inflate(R.layout.item_weibo_frame, parent, false)
42 | val subViewHolder = onCreateContentViewHolder(inflater, parent)
43 | return FrameHolder(root, subViewHolder, this)
44 | }
45 |
46 | override fun onBindViewHolder(holder: FrameHolder, item: Weibo) {
47 | holder.avatar.setImageResource(item.user.avatar)
48 | holder.username.text = item.user.name
49 | holder.createTime.text = item.createTime
50 | val weiboContent = item.content
51 | @Suppress("UNCHECKED_CAST")
52 | onBindContentViewHolder(holder.subViewHolder as SubViewHolder, weiboContent as Content)
53 | }
54 |
55 | class FrameHolder(itemView: View, val subViewHolder: ContentHolder, binder: WeiboFrameBinder<*, *>) : RecyclerView.ViewHolder(itemView) {
56 |
57 | val avatar: ImageView = itemView.findViewById(R.id.avatar)
58 | val username: TextView = itemView.findViewById(R.id.username)
59 | val createTime: TextView = itemView.findViewById(R.id.create_time)
60 | private val container: FrameLayout = itemView.findViewById(R.id.container)
61 | private val close: TextView = itemView.findViewById(R.id.close)
62 |
63 | init {
64 | container.addView(subViewHolder.itemView)
65 | this.subViewHolder.parent = this
66 |
67 | itemView.setOnClickListener { v -> Toast.makeText(v.context, "Position: $bindingAdapterPosition", LENGTH_SHORT).show() }
68 | close.setOnClickListener {
69 | val position = bindingAdapterPosition
70 | if (position != RecyclerView.NO_POSITION) {
71 | binder.adapter.items.toMutableList()
72 | .apply {
73 | removeAt(position)
74 | binder.adapter.items = this
75 | }
76 | binder.adapter.notifyItemRemoved(position)
77 | }
78 | }
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/sample/src/androidTest/kotlin/com/drakeet/multitype/sample/bilibili/BilibiliActivityDataSetADCTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.bilibili
18 |
19 | import androidx.test.espresso.Espresso.onView
20 | import androidx.test.espresso.assertion.ViewAssertions.matches
21 | import androidx.test.espresso.matcher.ViewMatchers.withText
22 | import androidx.test.rule.ActivityTestRule
23 | import androidx.test.runner.AndroidJUnit4
24 | import com.drakeet.multitype.MultiTypeAdapter
25 | import com.drakeet.multitype.sample.R
26 | import com.drakeet.multitype.sample.RecyclerViewMatcher.Companion.withRecyclerView
27 | import com.drakeet.multitype.sample.common.Category
28 | import org.junit.Before
29 | import org.junit.Rule
30 | import org.junit.Test
31 | import org.junit.runner.RunWith
32 |
33 | /**
34 | * @author Drakeet Xu
35 | */
36 | @RunWith(AndroidJUnit4::class)
37 | class BilibiliActivityDataSetADCTest {
38 |
39 | private val testTitle = "testTitle"
40 |
41 | private lateinit var items: MutableList
42 | private lateinit var adapter: MultiTypeAdapter
43 |
44 | @get:Rule
45 | var rule = ActivityTestRule(BilibiliActivity::class.java)
46 |
47 | @Before
48 | fun setup() {
49 | items = rule.activity.items
50 | adapter = rule.activity.adapter
51 | }
52 |
53 | @Test
54 | @Throws(Throwable::class)
55 | fun shouldNotFailWhenAddSingleTop() {
56 | val originalFirst = items[0]
57 | rule.runOnUiThread {
58 | items.add(originalFirst)
59 | adapter.notifyItemInserted(0)
60 | }
61 | }
62 |
63 | @Test
64 | @Throws(Throwable::class)
65 | fun shouldNotFailWhenAddMultiTop() {
66 | val originalFirst = items[0]
67 | rule.runOnUiThread {
68 | for (i in 0..29) {
69 | items.add(originalFirst)
70 | }
71 | adapter.notifyItemRangeInserted(0, 29)
72 | }
73 | }
74 |
75 | @Test
76 | @Throws(Throwable::class)
77 | fun shouldNotFailWhenDeleteFirst() {
78 | rule.runOnUiThread {
79 | items.removeAt(0)
80 | adapter.notifyItemRemoved(0)
81 | }
82 | }
83 |
84 | @Test
85 | @Throws(Throwable::class)
86 | fun shouldNotFailWhenDeleteEnd() {
87 | rule.runOnUiThread {
88 | val endIndex = items.size - 1
89 | items.removeAt(endIndex)
90 | adapter.notifyItemRemoved(endIndex)
91 | }
92 | }
93 |
94 | @Test
95 | @Throws(Throwable::class)
96 | fun shouldNotFailWhenDeleteAll() {
97 | rule.runOnUiThread {
98 | items.clear()
99 | adapter.notifyDataSetChanged()
100 | }
101 | }
102 |
103 | @Test
104 | @Throws(Throwable::class)
105 | fun shouldNotFailWhenChangeFirst() {
106 | rule.runOnUiThread {
107 | val category = items[0] as Category
108 | category.title = testTitle
109 | adapter.notifyItemChanged(0)
110 | }
111 |
112 | onView(withRecyclerView(R.id.list).atPositionOnView(0, R.id.title))
113 | .check(matches(withText(testTitle)))
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/weibo/WeiboActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.weibo
18 |
19 | import android.os.Bundle
20 | import androidx.recyclerview.widget.RecyclerView
21 | import com.drakeet.multitype.MultiTypeAdapter
22 | import com.drakeet.multitype.sample.MenuBaseActivity
23 | import com.drakeet.multitype.sample.R
24 | import com.drakeet.multitype.sample.weibo.content.SimpleImage
25 | import com.drakeet.multitype.sample.weibo.content.SimpleImageViewBinder
26 | import com.drakeet.multitype.sample.weibo.content.SimpleText
27 | import com.drakeet.multitype.sample.weibo.content.SimpleTextViewBinder
28 | import java.util.*
29 |
30 | /**
31 | * @author Drakeet Xu
32 | */
33 | class WeiboActivity : MenuBaseActivity() {
34 |
35 | private lateinit var adapter: MultiTypeAdapter
36 | private lateinit var items: MutableList
37 |
38 | override fun onCreate(savedInstanceState: Bundle?) {
39 | super.onCreate(savedInstanceState)
40 | setContentView(R.layout.activity_list)
41 | val recyclerView = findViewById(R.id.list)
42 |
43 | adapter = MultiTypeAdapter()
44 |
45 | adapter.register(Weibo::class).to(
46 | SimpleTextViewBinder(),
47 | SimpleImageViewBinder()
48 | ).withLinker { _, weibo ->
49 | when (weibo.content) {
50 | is SimpleText -> 0
51 | is SimpleImage -> 1
52 | else -> 0
53 | }
54 | }
55 |
56 | recyclerView.adapter = adapter
57 |
58 | items = ArrayList()
59 |
60 | val user = User("drakeet", R.drawable.avatar_drakeet)
61 | val simpleText = SimpleText("A simple text Weibo: Hello World.")
62 | val simpleImage = SimpleImage(R.drawable.img_10)
63 | for (i in 0..19) {
64 | items.add(Weibo(user, simpleText))
65 | items.add(Weibo(user, simpleImage))
66 | }
67 | adapter.items = items
68 | adapter.notifyDataSetChanged()
69 |
70 | loadRemoteData()
71 | }
72 |
73 | private fun loadRemoteData() {
74 | val weiboList = WeiboJsonParser.fromJson(
75 | JSON_FROM_SERVICE
76 | .replace("\$avatar", "" + R.drawable.avatar_drakeet)
77 | .replace("\$content", "" + R.drawable.img_00)
78 | )
79 | items = ArrayList(items)
80 | items.addAll(0, weiboList)
81 | adapter.items = items
82 | adapter.notifyDataSetChanged()
83 | }
84 |
85 | companion object {
86 | private const val JSON_FROM_SERVICE = """[
87 | {
88 | "content":{
89 | "text":"A simple text Weibo: JSON_FROM_SERVICE.",
90 | "content_type":"simple_text"
91 | },
92 | "createTime":"Just now",
93 | "user":{
94 | "avatar":${"$"}avatar,
95 | "name":"drakeet"
96 | }
97 | },
98 | {
99 | "content":{
100 | "resId":${"$"}content,
101 | "content_type":"simple_image"
102 | },
103 | "createTime":"Just now(JSON_FROM_SERVICE)",
104 | "user":{
105 | "avatar":${"$"}avatar,
106 | "name":"drakeet"
107 | }
108 | }
109 | ]"""
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/library/src/test/kotlin/com/drakeet/multitype/OneToManyBuilderTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype
18 |
19 | import androidx.recyclerview.widget.RecyclerView
20 | import com.google.common.truth.Truth.assertThat
21 | import com.nhaarman.mockitokotlin2.check
22 | import com.nhaarman.mockitokotlin2.mock
23 | import com.nhaarman.mockitokotlin2.times
24 | import com.nhaarman.mockitokotlin2.verify
25 | import org.junit.Test
26 | import kotlin.reflect.KClass
27 |
28 | /**
29 | * @author Drakeet Xu
30 | */
31 | class OneToManyBuilderTest {
32 |
33 | private class Data
34 |
35 | private val adapter: MultiTypeAdapter = mock()
36 |
37 | private val oneToManyBuilder = OneToManyBuilder(adapter, Data::class.java)
38 |
39 | @Test
40 | fun testWithLinker() {
41 | oneToManyBuilder.to(mock(), mock())
42 | oneToManyBuilder.withLinker(object : Linker {
43 | override fun index(position: Int, item: Data): Int {
44 | return position
45 | }
46 | })
47 | verify(adapter, times(2)).register(check> {
48 | assertThat(it.clazz).isEqualTo(Data::class.java)
49 | assertThat(it.linker.index(1, Data())).isEqualTo(1)
50 | })
51 |
52 | oneToManyBuilder.withLinker { position, item -> position }
53 | verify(adapter, times(4)).register(check> {
54 | assertThat(it.clazz).isEqualTo(Data::class.java)
55 | assertThat(it.linker.index(2, Data())).isEqualTo(2)
56 | })
57 | }
58 |
59 | private abstract class DataItemViewDelegate : ItemViewDelegate()
60 |
61 | @Test
62 | fun testWithJavaClassLinker() {
63 | val itemViewDelegate1 = mock>()
64 | val itemViewDelegate2 = mock()
65 | oneToManyBuilder.to(itemViewDelegate1, itemViewDelegate2)
66 | oneToManyBuilder.withJavaClassLinker(object : JavaClassLinker {
67 | override fun index(position: Int, item: Data): Class> {
68 | return if (position == 3) itemViewDelegate1.javaClass else itemViewDelegate2.javaClass
69 | }
70 | })
71 | verify(adapter, times(2)).register(check> {
72 | assertThat(it.clazz).isEqualTo(Data::class.java)
73 | assertThat(it.linker.index(3, Data())).isEqualTo(0)
74 | assertThat(it.linker.index(5, Data())).isEqualTo(1)
75 | })
76 |
77 | oneToManyBuilder.withKotlinClassLinker { position, item ->
78 | if (position == 3) itemViewDelegate1::class else itemViewDelegate2::class
79 | }
80 | verify(adapter, times(4)).register(check> {
81 | assertThat(it.clazz).isEqualTo(Data::class.java)
82 | assertThat(it.linker.index(3, Data())).isEqualTo(0)
83 | assertThat(it.linker.index(5, Data())).isEqualTo(1)
84 | })
85 | oneToManyBuilder.withKotlinClassLinker(object : KotlinClassLinker {
86 | override fun index(position: Int, item: Data): KClass> {
87 | return if (position == 3) itemViewDelegate1::class else itemViewDelegate2::class
88 | }
89 | })
90 | verify(adapter, times(6)).register(check> {
91 | assertThat(it.clazz).isEqualTo(Data::class.java)
92 | assertThat(it.linker.index(3, Data())).isEqualTo(0)
93 | assertThat(it.linker.index(5, Data())).isEqualTo(1)
94 | })
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/bilibili/BilibiliActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.bilibili
18 |
19 | import android.os.Bundle
20 | import android.view.Menu
21 | import androidx.annotation.VisibleForTesting
22 | import androidx.recyclerview.widget.GridLayoutManager
23 | import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup
24 | import androidx.recyclerview.widget.RecyclerView
25 | import com.drakeet.multitype.MultiTypeAdapter
26 | import com.drakeet.multitype.sample.MenuBaseActivity
27 | import com.drakeet.multitype.sample.R
28 | import com.drakeet.multitype.sample.common.Category
29 | import com.drakeet.multitype.sample.common.CategoryHolderInflater
30 | import java.util.*
31 |
32 | /**
33 | * @author Drakeet Xu
34 | */
35 | class BilibiliActivity : MenuBaseActivity() {
36 |
37 | @VisibleForTesting
38 | internal lateinit var items: MutableList
39 | @VisibleForTesting
40 | internal lateinit var adapter: MultiTypeAdapter
41 |
42 | private class JsonData {
43 |
44 | private val post00 = Post(R.drawable.img_00, PREFIX + "post00")
45 | private val post01 = Post(R.drawable.img_01, PREFIX + "post01")
46 | private val post10 = Post(R.drawable.img_10, PREFIX + "post10")
47 | private val post11 = Post(R.drawable.img_11, PREFIX + "post11")
48 |
49 | internal var category0 = Category("title0")
50 | internal var postArray = arrayOf(post00, post01, post10, post11)
51 |
52 | internal var postList: MutableList = ArrayList()
53 |
54 | init {
55 | postList.add(post00)
56 | postList.add(post00)
57 | postList.add(post00)
58 | postList.add(post00)
59 | postList.add(post00)
60 | postList.add(post00)
61 | }
62 |
63 | companion object {
64 | private const val PREFIX = "这是一条长长的达到两行的标题文字"
65 | }
66 | }
67 |
68 | override fun onCreate(savedInstanceState: Bundle?) {
69 | super.onCreate(savedInstanceState)
70 | setContentView(R.layout.activity_list)
71 |
72 | adapter = MultiTypeAdapter()
73 | adapter.register(CategoryHolderInflater())
74 |
75 | adapter.register(PostViewBinder())
76 | adapter.register(HorizontalPostsHolderInflater())
77 |
78 | val recyclerView = findViewById(R.id.list)
79 |
80 | val layoutManager = GridLayoutManager(this, SPAN_COUNT)
81 | val spanSizeLookup = object : SpanSizeLookup() {
82 | override fun getSpanSize(position: Int): Int {
83 | val item = items[position]
84 | return if (item is PostList || item is Category) SPAN_COUNT else 1
85 | }
86 | }
87 | layoutManager.spanSizeLookup = spanSizeLookup
88 | recyclerView.layoutManager = layoutManager
89 | val space = resources.getDimensionPixelSize(R.dimen.normal_space)
90 | recyclerView.addItemDecoration(PostItemDecoration(space, spanSizeLookup))
91 |
92 | recyclerView.adapter = adapter
93 |
94 | val data = JsonData()
95 | items = ArrayList()
96 | for (i in 0..9) {
97 | /* You also could use Category as your CategoryItemContent directly */
98 | items.add(data.category0)
99 | items.add(data.postArray[0])
100 | items.add(data.postArray[1])
101 | items.add(data.postArray[2])
102 | items.add(data.postArray[3])
103 | items.add(data.postArray[0])
104 | items.add(data.postArray[1])
105 | items.add(PostList(data.postList))
106 | }
107 | adapter.items = items
108 | adapter.notifyDataSetChanged()
109 | }
110 |
111 | override fun onCreateOptionsMenu(menu: Menu): Boolean {
112 | val inflater = menuInflater
113 | inflater.inflate(R.menu.menu_main, menu)
114 | return true
115 | }
116 |
117 | companion object {
118 | private const val SPAN_COUNT = 2
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/library/src/test/kotlin/com/drakeet/multitype/MultiTypeAdapterTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype
18 |
19 | import android.content.Context
20 | import android.view.LayoutInflater
21 | import android.view.ViewGroup
22 | import com.google.common.truth.Truth.assertThat
23 | import com.nhaarman.mockitokotlin2.*
24 | import org.junit.Assert.assertEquals
25 | import org.junit.Before
26 | import org.junit.Test
27 | import org.junit.runner.RunWith
28 | import org.mockito.ArgumentMatchers.anyList
29 | import org.mockito.ArgumentMatchers.anyString
30 | import org.robolectric.RobolectricTestRunner
31 | import java.util.*
32 |
33 | /**
34 | * @author Drakeet Xu
35 | */
36 | @RunWith(RobolectricTestRunner::class)
37 | class MultiTypeAdapterTest {
38 |
39 | private val parent: ViewGroup = mock()
40 | private val context: Context = mock()
41 | private val mockedItemViewDelegate: TestItemViewDelegate = mock()
42 |
43 | private val itemViewDelegate = TestItemViewDelegate()
44 |
45 | @Before
46 | @Throws(Exception::class)
47 | fun setUp() {
48 | whenever(parent.context).thenReturn(context)
49 | }
50 |
51 | @Test
52 | fun shouldReturnOriginalItems() {
53 | val list = ArrayList()
54 | val adapter = MultiTypeAdapter(list)
55 | assertEquals(list, adapter.items)
56 | }
57 |
58 | @Test
59 | fun shouldReturnEmptyItemsWithDefaultConstructor() {
60 | val adapter = MultiTypeAdapter()
61 | assertThat(adapter.items).isEmpty()
62 | }
63 |
64 | @Test
65 | fun shouldOverrideRegisteredDelegate() {
66 | val adapter = MultiTypeAdapter()
67 | adapter.register(TestItem::class, itemViewDelegate)
68 | assertThat(adapter.types.size).isEqualTo(1)
69 | assertThat(itemViewDelegate).isEqualTo(adapter.types.getType(0).delegate)
70 |
71 | val newDelegate = TestItemViewDelegate()
72 | adapter.register(TestItem::class, newDelegate)
73 | assertThat(newDelegate).isEqualTo(adapter.types.getType(0).delegate)
74 | }
75 |
76 | @Test
77 | fun shouldNotOverrideRegisteredDelegateWhenToMany() {
78 | val adapter = MultiTypeAdapter()
79 | val delegate2 = TestItemViewDelegate()
80 | adapter.register(TestItem::class)
81 | .to(itemViewDelegate, delegate2)
82 | .withLinker { _, _ -> -1 }
83 | assertThat(adapter.types.getType(0).clazz).isEqualTo(TestItem::class.java)
84 | assertThat(adapter.types.getType(1).clazz).isEqualTo(TestItem::class.java)
85 |
86 | assertThat(itemViewDelegate).isEqualTo(adapter.types.getType(0).delegate)
87 | assertThat(delegate2).isEqualTo(adapter.types.getType(1).delegate)
88 | }
89 |
90 | @Test
91 | fun testOnCreateViewHolder() {
92 | val adapter = MultiTypeAdapter()
93 | adapter.register(TestItem::class, mockedItemViewDelegate)
94 | val item = TestItem("testOnCreateViewHolder")
95 | adapter.items = listOf(item)
96 | val type = adapter.getItemViewType(0)
97 |
98 | adapter.onCreateViewHolder(parent, type)
99 | verify(mockedItemViewDelegate).onCreateViewHolder(context, parent)
100 | }
101 |
102 | @Test
103 | fun testOnBindViewHolder() {
104 | val adapter = MultiTypeAdapter()
105 | adapter.register(TestItem::class, mockedItemViewDelegate)
106 | val item = TestItem("testOnCreateViewHolder")
107 | adapter.items = listOf(item)
108 |
109 | val holder: TestItemViewDelegate.ViewHolder = mock()
110 | whenever(holder.itemViewType).thenReturn(adapter.getItemViewType(0))
111 | adapter.onBindViewHolder(holder, 0)
112 | verify(mockedItemViewDelegate).onBindViewHolder(eq(holder), eq(item), anyList())
113 |
114 | val payloads = emptyList()
115 | adapter.onBindViewHolder(holder, 0, payloads)
116 | verify(mockedItemViewDelegate, times(2)).onBindViewHolder(holder, item, payloads)
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
25 |
26 |
27 |
28 |
32 |
33 |
34 |
35 |
42 |
43 |
47 |
48 |
58 |
59 |
66 |
67 |
73 |
74 |
77 |
78 |
84 |
85 |
86 |
87 |
94 |
95 |
100 |
101 |
109 |
110 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/sample/src/main/kotlin/com/drakeet/multitype/sample/more/MoreApisPlayground.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.more
18 |
19 | import android.annotation.SuppressLint
20 | import android.os.Bundle
21 | import android.os.SystemClock.currentThreadTimeMillis
22 | import android.view.LayoutInflater
23 | import android.view.View
24 | import android.view.ViewGroup
25 | import android.widget.TextView
26 | import androidx.annotation.VisibleForTesting
27 | import androidx.recyclerview.widget.RecyclerView
28 | import com.drakeet.multitype.ItemViewBinder
29 | import com.drakeet.multitype.MultiTypeAdapter
30 | import com.drakeet.multitype.sample.MenuBaseActivity
31 | import com.drakeet.multitype.sample.R
32 | import com.drakeet.multitype.sample.normal.TextItem
33 | import java.util.*
34 |
35 | /**
36 | * @author Drakeet Xu
37 | */
38 | @SuppressLint("SetTextI18n")
39 | class MoreApisPlayground : MenuBaseActivity() {
40 |
41 | private lateinit var terminal: TextView
42 | private lateinit var recyclerView: RecyclerView
43 |
44 | @VisibleForTesting
45 | lateinit var adapter: MultiTypeAdapter
46 | @VisibleForTesting
47 | lateinit var items: MutableList
48 |
49 | override fun onCreate(savedInstanceState: Bundle?) {
50 | super.onCreate(savedInstanceState)
51 | setContentView(R.layout.activity_more_apis_playground)
52 | recyclerView = findViewById(R.id.list)
53 | terminal = findViewById(R.id.terminal)
54 | terminal.text = TERMINAL_DEFAULT_TEXT
55 |
56 | items = ArrayList()
57 | adapter = MultiTypeAdapter()
58 |
59 | adapter.register(ObservableTextItemViewBinder())
60 | recyclerView.adapter = adapter
61 |
62 | for (i in 0..199) {
63 | items.add(TextItem(i.toString()))
64 | }
65 | adapter.items = items
66 | adapter.notifyDataSetChanged()
67 | }
68 |
69 | fun onAdd(view: View) {
70 | val bottom = items.size - 1
71 | items.add(TextItem(currentThreadTimeMillis().toString()))
72 | adapter.notifyItemInserted(bottom + 1)
73 | recyclerView.scrollToPosition(bottom + 1)
74 | }
75 |
76 | fun onRemove(view: View) {
77 | val bottom = items.size - 1
78 | recyclerView.scrollToPosition(bottom)
79 | items.removeAt(bottom)
80 | adapter.notifyItemRemoved(bottom)
81 | }
82 |
83 | fun onClear(view: View) {
84 | items.clear()
85 | adapter.notifyDataSetChanged()
86 | }
87 |
88 | private inner class ObservableTextItemViewBinder : ItemViewBinder() {
89 |
90 | private var buffer = 0
91 |
92 | inner class TextHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
93 | val text: TextView = itemView.findViewById(R.id.text)
94 | }
95 |
96 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): TextHolder {
97 | val root = inflater.inflate(R.layout.item_text, parent, false)
98 | return TextHolder(root)
99 | }
100 |
101 | override fun onBindViewHolder(holder: TextHolder, item: TextItem) {
102 | holder.text.text = "observable item(" + item.text + ")"
103 | }
104 |
105 | override fun onViewRecycled(holder: TextHolder) {
106 | appendTerminalLine("onViewRecycled: " + holder.text.text)
107 | }
108 |
109 | override fun onFailedToRecycleView(holder: TextHolder): Boolean {
110 | appendTerminalLine("onFailedToRecycleView: " + holder.text.text)
111 | return true
112 | }
113 |
114 | override fun onViewAttachedToWindow(holder: TextHolder) {
115 | appendTerminalLine("onViewAttachedToWindow: " + holder.text.text)
116 | }
117 |
118 | override fun onViewDetachedFromWindow(holder: TextHolder) {
119 | appendTerminalLine("onViewDetachedFromWindow: " + holder.text.text)
120 | }
121 |
122 | private fun appendTerminalLine(line: String) {
123 | if (buffer == 5) {
124 | terminal.text = TERMINAL_DEFAULT_TEXT
125 | buffer = 0
126 | }
127 | terminal.append("\n" + line)
128 | buffer++
129 | }
130 | }
131 |
132 | companion object {
133 |
134 | private const val TERMINAL_DEFAULT_TEXT = "ObservableTextItemViewBinder: "
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/sample/src/androidTest/kotlin/com/drakeet/multitype/sample/one2many/DuplicateTypesTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-present. Drakeet Xu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.drakeet.multitype.sample.one2many
18 |
19 | import androidx.test.filters.LargeTest
20 | import androidx.test.rule.ActivityTestRule
21 | import androidx.test.runner.AndroidJUnit4
22 | import com.google.common.truth.Truth.assertThat
23 | import com.drakeet.multitype.Linker
24 | import com.drakeet.multitype.MultiTypeAdapter
25 | import org.junit.Assert.assertEquals
26 | import org.junit.Assert.assertSame
27 | import org.junit.Before
28 | import org.junit.Rule
29 | import org.junit.Test
30 | import org.junit.runner.RunWith
31 |
32 | @LargeTest
33 | @RunWith(AndroidJUnit4::class)
34 | class DuplicateTypesTest {
35 |
36 | private lateinit var adapter: MultiTypeAdapter
37 |
38 | @get:Rule
39 | var rule = ActivityTestRule(OneDataToManyActivity::class.java)
40 |
41 | @Before
42 | @Throws(Throwable::class)
43 | fun setup() {
44 | adapter = rule.activity.adapter
45 | }
46 |
47 | private fun resetRecyclerViewState() {
48 | // reset and clear the recycler view types to recreate view holder
49 | rule.activity.recyclerView.adapter = adapter
50 | }
51 |
52 | @Test
53 | @Throws(Throwable::class)
54 | fun shouldOneOverrideMany() {
55 | rule.runOnUiThread {
56 | resetRecyclerViewState()
57 | adapter.register(DataType1ViewBinder())
58 | adapter.notifyDataSetChanged()
59 | }
60 | assertThat(adapter.types.size).isEqualTo(1)
61 | assertThat(adapter.types.getType(0).clazz).isEqualTo(Data::class.java)
62 | assertThat(adapter.types.getType(0).delegate.javaClass).isEqualTo(DataType1ViewBinder::class.java)
63 | }
64 |
65 | @Test
66 | @Throws(Throwable::class)
67 | fun shouldOneOverrideOne() {
68 | rule.runOnUiThread {
69 | resetRecyclerViewState()
70 | adapter.register(DataType1ViewBinder())
71 | adapter.register(DataType2ViewBinder())
72 | adapter.notifyDataSetChanged()
73 | }
74 | assertThat(adapter.types.size).isEqualTo(1)
75 | assertThat(adapter.types.getType(0).clazz).isEqualTo(Data::class.java)
76 | assertThat(adapter.types.getType(0).delegate.javaClass).isEqualTo(DataType2ViewBinder::class.java)
77 | }
78 |
79 | @Test
80 | @Throws(Throwable::class)
81 | fun shouldManyOverrideOne() {
82 | val linker = object : Linker {
83 | override fun index(position: Int, item: Data): Int {
84 | return if (item.type == Data.TYPE_1) 1 else 0
85 | }
86 | }
87 | rule.runOnUiThread {
88 | resetRecyclerViewState()
89 | adapter.register(DataType1ViewBinder())
90 |
91 | adapter.register(Data::class).to(
92 | DataType2ViewBinder(),
93 | DataType1ViewBinder()
94 | ).withLinker(linker)
95 | adapter.notifyDataSetChanged()
96 | }
97 | assertThat(adapter.types.size).isEqualTo(2)
98 |
99 | assertEquals(Data::class.java, adapter.types.getType(0).clazz)
100 | assertEquals(Data::class.java, adapter.types.getType(1).clazz)
101 |
102 | assertEquals(
103 | DataType2ViewBinder::class.java,
104 | adapter.types.getType(0).delegate::class.java
105 | )
106 | assertEquals(
107 | DataType1ViewBinder::class.java,
108 | adapter.types.getType(1).delegate::class.java
109 | )
110 |
111 | assertSame(linker, adapter.types.getType(0).linker)
112 | assertSame(linker, adapter.types.getType(1).linker)
113 | }
114 |
115 | @Test
116 | @Throws(Throwable::class)
117 | fun shouldManyOverrideMany() {
118 | val linker = object : Linker {
119 | override fun index(position: Int, item: Data): Int {
120 | return if (item.type == Data.TYPE_1) 1 else 0
121 | }
122 | }
123 | rule.runOnUiThread {
124 | resetRecyclerViewState()
125 | adapter.register(Data::class).to(
126 | DataType2ViewBinder(),
127 | DataType1ViewBinder()
128 | ).withLinker(linker)
129 |
130 | adapter.register(Data::class).to(
131 | DataType1ViewBinder(),
132 | DataType2ViewBinder()
133 | ).withLinker(linker)
134 | adapter.notifyDataSetChanged()
135 | }
136 | assertThat(adapter.types.size).isEqualTo(2)
137 |
138 | assertEquals(Data::class.java, adapter.types.getType(0).clazz)
139 | assertEquals(Data::class.java, adapter.types.getType(1).clazz)
140 |
141 | assertEquals(
142 | DataType1ViewBinder::class.java,
143 | adapter.types.getType(0).delegate::class.java
144 | )
145 | assertEquals(
146 | DataType2ViewBinder::class.java,
147 | adapter.types.getType(1).delegate::class.java
148 | )
149 |
150 | assertSame(linker, adapter.types.getType(0).linker)
151 | assertSame(linker, adapter.types.getType(1).linker)
152 | }
153 | }
154 |
--------------------------------------------------------------------------------