├── .gitignore
├── .gradle
└── 2.2.1
│ └── taskArtifacts
│ ├── cache.properties
│ ├── cache.properties.lock
│ ├── fileHashes.bin
│ ├── fileSnapshots.bin
│ ├── outputFileStates.bin
│ └── taskArtifacts.bin
├── LICENSE
├── README.md
├── advanceadapter
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── zzhoujay
│ │ └── advanceadapter
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── zzhoujay
│ │ │ └── advanceadapter
│ │ │ ├── AdvanceAdapter.java
│ │ │ ├── DynamicAdapter.java
│ │ │ └── SingleAdapter.java
│ └── res
│ │ └── values
│ │ └── strings.xml
│ └── test
│ └── java
│ └── com
│ └── zzhoujay
│ └── advanceadapter
│ └── ExampleUnitTest.java
├── build.gradle
├── build
└── intermediates
│ ├── dex-cache
│ └── cache.xml
│ └── gradle_project_sync_data.bin
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── images
├── image1.png
├── image2.png
└── image3.png
├── settings.gradle
└── simple
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
├── androidTest
└── java
│ └── com
│ └── zzhoujay
│ └── advanceadaptersimple
│ └── ApplicationTest.java
├── main
├── AndroidManifest.xml
├── java
│ └── com
│ │ └── zzhoujay
│ │ └── advanceadaptersimple
│ │ ├── MainActivity.java
│ │ └── NormalAdapter.java
└── res
│ ├── layout
│ ├── activity_main.xml
│ ├── footer.xml
│ ├── header.xml
│ └── item.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
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
└── test
└── java
└── com
└── zzhoujay
└── advanceadaptersimple
└── ExampleUnitTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Android template
3 | # Built application files
4 | *.apk
5 | *.ap_
6 |
7 | # Files for the Dalvik VM
8 | *.dex
9 |
10 | # Java class files
11 | *.class
12 |
13 | # Generated files
14 | bin/
15 | gen/
16 | out/
17 |
18 | # Gradle files
19 | .gradle/
20 | build/
21 |
22 | # Local configuration file (sdk path, etc)
23 | local.properties
24 |
25 | # Proguard folder generated by Eclipse
26 | proguard/
27 |
28 | # Log Files
29 | *.log
30 |
31 | # Android Studio Navigation editor temp files
32 | .navigation/
33 |
34 | # Android Studio captures folder
35 | captures/
36 |
37 | # Intellij
38 | *.iml
39 |
40 | # Keystore files
41 | *.jks
42 | ### Eclipse template
43 |
44 | .metadata
45 | bin/
46 | tmp/
47 | *.tmp
48 | *.bak
49 | *.swp
50 | *~.nib
51 | local.properties
52 | .settings/
53 | .loadpath
54 | .recommenders
55 |
56 | # Eclipse Core
57 | .project
58 |
59 | # External tool builders
60 | .externalToolBuilders/
61 |
62 | # Locally stored "Eclipse launch configurations"
63 | *.launch
64 |
65 | # PyDev specific (Python IDE for Eclipse)
66 | *.pydevproject
67 |
68 | # CDT-specific (C/C++ Development Tooling)
69 | .cproject
70 |
71 | # JDT-specific (Eclipse Java Development Tools)
72 | .classpath
73 |
74 | # Java annotation processor (APT)
75 | .factorypath
76 |
77 | # PDT-specific (PHP Development Tools)
78 | .buildpath
79 |
80 | # sbteclipse plugin
81 | .target
82 |
83 | # Tern plugin
84 | .tern-project
85 |
86 | # TeXlipse plugin
87 | .texlipse
88 |
89 | # STS (Spring Tool Suite)
90 | .springBeans
91 |
92 | # Code Recommenders
93 | .recommenders/
94 | ### OSX template
95 | .DS_Store
96 | .AppleDouble
97 | .LSOverride
98 |
99 | # Icon must end with two \r
100 | Icon
101 |
102 | # Thumbnails
103 | ._*
104 |
105 | # Files that might appear in the root of a volume
106 | .DocumentRevisions-V100
107 | .fseventsd
108 | .Spotlight-V100
109 | .TemporaryItems
110 | .Trashes
111 | .VolumeIcon.icns
112 |
113 | # Directories potentially created on remote AFP share
114 | .AppleDB
115 | .AppleDesktop
116 | Network Trash Folder
117 | Temporary Items
118 | .apdisk
119 | ### Gradle template
120 | .gradle
121 | build/
122 |
123 | # Ignore Gradle GUI config
124 | gradle-app.setting
125 |
126 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
127 | !gradle-wrapper.jar
128 |
129 | # Cache of project
130 | .gradletasknamecache
131 |
132 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
133 | # gradle/wrapper/gradle-wrapper.properties
134 | ### Windows template
135 | # Windows image file caches
136 | Thumbs.db
137 | ehthumbs.db
138 |
139 | # Folder config file
140 | Desktop.ini
141 |
142 | # Recycle Bin used on file shares
143 | $RECYCLE.BIN/
144 |
145 | # Windows Installer files
146 | *.cab
147 | *.msi
148 | *.msm
149 | *.msp
150 |
151 | # Windows shortcuts
152 | *.lnk
153 | ### Linux template
154 | *~
155 |
156 | # temporary files which can be created if a process still has a handle open of a deleted file
157 | .fuse_hidden*
158 |
159 | # KDE directory preferences
160 | .directory
161 |
162 | # Linux trash folder which might appear on any partition or disk
163 | .Trash-*
164 | ### JDeveloper template
165 | # default application storage directory used by the IDE Performance Cache feature
166 | .data/
167 |
168 | # used for ADF styles caching
169 | temp/
170 |
171 | # default output directories
172 | classes/
173 | deploy/
174 | javadoc/
175 |
176 | # lock file, a part of Oracle Credential Store Framework
177 | cwallet.sso.lck### JetBrains template
178 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
179 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
180 |
181 | # User-specific stuff:
182 | .idea/workspace.xml
183 | .idea/tasks.xml
184 | .idea/dictionaries
185 | .idea/vcs.xml
186 | .idea/jsLibraryMappings.xml
187 |
188 | # Sensitive or high-churn files:
189 | .idea/dataSources.ids
190 | .idea/dataSources.xml
191 | .idea/dataSources.local.xml
192 | .idea/sqlDataSources.xml
193 | .idea/dynamic.xml
194 | .idea/uiDesigner.xml
195 |
196 | # Gradle:
197 | .idea/gradle.xml
198 | .idea/libraries
199 |
200 | # Mongo Explorer plugin:
201 | .idea/mongoSettings.xml
202 |
203 | ## File-based project format:
204 | *.iws
205 |
206 | ## Plugin-specific files:
207 |
208 | # IntelliJ
209 | /out/
210 |
211 | # mpeltonen/sbt-idea plugin
212 | .idea_modules/
213 |
214 | # JIRA plugin
215 | atlassian-ide-plugin.xml
216 |
217 | # Crashlytics plugin (for Android Studio and IntelliJ)
218 | com_crashlytics_export_strings.xml
219 | crashlytics.properties
220 | crashlytics-build.properties
221 | fabric.properties
222 | ### NetBeans template
223 | nbproject/private/
224 | build/
225 | nbbuild/
226 | dist/
227 | nbdist/
228 | nbactions.xml
229 | .nb-gradle/
230 |
231 |
--------------------------------------------------------------------------------
/.gradle/2.2.1/taskArtifacts/cache.properties:
--------------------------------------------------------------------------------
1 | #Wed Jul 22 12:25:47 CST 2015
2 |
--------------------------------------------------------------------------------
/.gradle/2.2.1/taskArtifacts/cache.properties.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzhoujay/AdvanceAdapter/73a629787e9b7fcc196b322680482676b8a8b306/.gradle/2.2.1/taskArtifacts/cache.properties.lock
--------------------------------------------------------------------------------
/.gradle/2.2.1/taskArtifacts/fileHashes.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzhoujay/AdvanceAdapter/73a629787e9b7fcc196b322680482676b8a8b306/.gradle/2.2.1/taskArtifacts/fileHashes.bin
--------------------------------------------------------------------------------
/.gradle/2.2.1/taskArtifacts/fileSnapshots.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzhoujay/AdvanceAdapter/73a629787e9b7fcc196b322680482676b8a8b306/.gradle/2.2.1/taskArtifacts/fileSnapshots.bin
--------------------------------------------------------------------------------
/.gradle/2.2.1/taskArtifacts/outputFileStates.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzhoujay/AdvanceAdapter/73a629787e9b7fcc196b322680482676b8a8b306/.gradle/2.2.1/taskArtifacts/outputFileStates.bin
--------------------------------------------------------------------------------
/.gradle/2.2.1/taskArtifacts/taskArtifacts.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzhoujay/AdvanceAdapter/73a629787e9b7fcc196b322680482676b8a8b306/.gradle/2.2.1/taskArtifacts/taskArtifacts.bin
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 zzhoujay
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AdvanceAdapter
2 |
3 | > 可以添加Header和Footer的Adapter
4 |
5 | * 低侵入性,采用装饰器的方式包裹正真的Adapter,无需修改原本Adapter
6 | * 支持`LinearLayoutManager`、`GridLayoutManager`、`StaggeredGridLayoutManager`
7 | * 可自定义Header和Footer的增加方式
8 |
9 | ### 运行效果
10 |
11 | 
12 | 
13 | 
14 |
15 | ### 注意
16 |
17 | 1. 在子Adapter中ViewHolder中调用getLayoutPosition()和getAdapterPosition()时会包含外层已添加的Header和Footer
18 |
19 | 2. 默认Header和Footer数量最大为100,且`ViewType`中的`Integer.MIN_VALUE`~`Integer.MIN_VALUE+100`、`Integer.MAX_VALUE-100`~`Integer.MAX_VALUE`均被占用
20 |
21 | ### 使用方法
22 |
23 | 1. 继承`AdvanceAdapter`并实现其中的抽象方法
24 |
25 | 2. 使用`AdvanceAdapter`的两个实现类:`DynamicAdapter`、`SingleAdapter`
26 |
27 | ```
28 | // 包裹你的Adapter,若是GridLayoutManager或StaggeredGridLayoutManager需要传入layoutManager
29 | AdvanceAdapter advanceAdapter=new DynamicAdapter(normalAdapter,layoutManager);
30 | // 给你的RecyclerView设置advanceAdapter
31 | recyclerView.setAdapter(advanceAdapter);
32 | ```
33 |
34 | ### gradle引用方法
35 | ```
36 | repositories {
37 | maven {
38 | url "http://dl.bintray.com/zzhoujay/maven"
39 | }
40 | }
41 |
42 | dependencies {
43 | compile 'com.zzhoujay.advanceadapter:advanceadapter:1.0.2'
44 | }
45 | ```
46 |
47 |
48 |
49 | _by zzhoujay_
--------------------------------------------------------------------------------
/advanceadapter/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/advanceadapter/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.github.dcendents.android-maven'
3 | apply plugin: 'com.jfrog.bintray'
4 |
5 | android {
6 | compileSdkVersion 23
7 | buildToolsVersion "23.0.2"
8 |
9 | defaultConfig {
10 | minSdkVersion 8
11 | targetSdkVersion 23
12 | versionCode 3
13 | versionName "1.0.2"
14 | }
15 | buildTypes {
16 | release {
17 | minifyEnabled false
18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19 | }
20 | }
21 | android {
22 | lintOptions {
23 | abortOnError false
24 | }
25 | }
26 | }
27 |
28 | dependencies {
29 | compile fileTree(dir: 'libs', include: ['*.jar'])
30 | testCompile 'junit:junit:4.12'
31 | compile 'com.android.support:recyclerview-v7:23.2.1'
32 |
33 | }
34 |
35 |
36 |
37 | version = "1.0.2"
38 |
39 |
40 | def siteUrl = 'https://github.com/zzhoujay/AdvanceAdapter' // 项目的主页
41 | def gitUrl = 'https://github.com/zzhoujay/AdvanceAdapter.git' // Git仓库的url
42 | group = "com.zzhoujay.advanceadapter" // Maven Group ID for the artifact,一般填你唯一的包名
43 | install {
44 | repositories.mavenInstaller {
45 | // This generates POM.xml with proper parameters
46 | pom {
47 | project {
48 | packaging 'aar'
49 | name 'AdvanceAdapter'
50 | url siteUrl
51 | licenses {
52 | license {
53 | name 'The MIT License (MIT)'
54 | url 'http://www.opensource.org/licenses/mit-license.php'
55 | }
56 | }
57 | developers {
58 | developer {
59 | id 'zzhoujay'
60 | name '郑州'
61 | email '1582519486@qq.com'
62 | }
63 | }
64 | scm {
65 | connection gitUrl
66 | developerConnection gitUrl
67 | url siteUrl
68 | }
69 | }
70 | }
71 | }
72 | }
73 |
74 | task sourcesJar(type: Jar) {
75 | from android.sourceSets.main.java.srcDirs
76 | classifier = 'sources'
77 | }
78 |
79 | task javadoc(type: Javadoc) {
80 | options.encoding='utf-8'
81 | source = android.sourceSets.main.java.srcDirs
82 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
83 | }
84 |
85 | task javadocJar(type: Jar, dependsOn: javadoc) {
86 | classifier = 'javadoc'
87 | from javadoc.destinationDir
88 | }
89 |
90 | artifacts {
91 | archives javadocJar
92 | archives sourcesJar
93 | }
94 |
95 | Properties properties = new Properties()
96 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
97 | bintray {
98 | user = properties.getProperty("bintray.user")
99 | key = properties.getProperty("bintray.apikey")
100 | configurations = ['archives']
101 | pkg {
102 | repo = "maven"
103 | name = "AdvanceAdapter" // project name in jcenter
104 | websiteUrl = siteUrl
105 | vcsUrl = gitUrl
106 | licenses = ["MIT"]
107 | publish = true
108 | }
109 | }
--------------------------------------------------------------------------------
/advanceadapter/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 /home/zhou/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 |
--------------------------------------------------------------------------------
/advanceadapter/src/androidTest/java/com/zzhoujay/advanceadapter/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.zzhoujay.advanceadapter;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/advanceadapter/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/advanceadapter/src/main/java/com/zzhoujay/advanceadapter/AdvanceAdapter.java:
--------------------------------------------------------------------------------
1 | package com.zzhoujay.advanceadapter;
2 |
3 | import android.support.v7.widget.GridLayoutManager;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.support.v7.widget.StaggeredGridLayoutManager;
6 | import android.view.ViewGroup;
7 |
8 | import java.util.List;
9 |
10 | /**
11 | * Created by zhou on 16-3-24.
12 | * 拥有Header和Footer的Adapter
13 | */
14 | public abstract class AdvanceAdapter extends RecyclerView.Adapter {
15 |
16 | public static final int MAX_HEADER_SIZE = 100;
17 | public static final int MAX_FOOTER_SIZE = 100;
18 | public static final int TYPE_HEADER_START = Integer.MAX_VALUE - MAX_HEADER_SIZE;
19 | public static final int TYPE_FOOTER_START = Integer.MIN_VALUE;
20 |
21 | private RecyclerView.Adapter childAdapter;
22 | private RecyclerView.LayoutManager layoutManager;
23 | private boolean isStaggered;
24 |
25 | /**
26 | * 适用于LinearLayoutManager
27 | *
28 | * @param childAdapter 被包裹的adapter
29 | */
30 | public AdvanceAdapter(RecyclerView.Adapter childAdapter) {
31 | this(childAdapter, null);
32 | }
33 |
34 | /**
35 | * 适用于GridLayoutManager和StaggeredGridLayoutManager
36 | *
37 | * @param childAdapter 被包裹的adapter
38 | * @param layoutManager recyclerView的layoutManager
39 | */
40 | public AdvanceAdapter(RecyclerView.Adapter childAdapter, RecyclerView.LayoutManager layoutManager) {
41 | this.childAdapter = childAdapter;
42 | this.layoutManager = layoutManager;
43 | if (layoutManager instanceof GridLayoutManager) {
44 | ((GridLayoutManager) layoutManager).setSpanSizeLookup(new GridSpanSizeLookup(this, (GridLayoutManager) layoutManager));
45 | } else if (layoutManager instanceof StaggeredGridLayoutManager) {
46 | isStaggered = true;
47 | }
48 | }
49 |
50 | /**
51 | * Header的数量
52 | *
53 | * @return header count
54 | */
55 | public abstract int headerCount();
56 |
57 | /**
58 | * Footer的数量
59 | *
60 | * @return footer count
61 | */
62 | public abstract int footerCount();
63 |
64 | /**
65 | * 创建Header的Holder
66 | *
67 | * @param parent parent
68 | * @param viewType TYPE_HEADER_START~Integer.MAX_VALUE,代表Header顺序
69 | * @return holder
70 | */
71 | public abstract RecyclerView.ViewHolder onHeaderCreateViewHolder(ViewGroup parent, int viewType);
72 |
73 | /**
74 | * 创建Footer的Holder
75 | *
76 | * @param parent parent
77 | * @param viewType TYPE_FOOTER_START~Integer.MIN_VALUE+MAX_FOOTER_SIZE,代表Footer的顺序
78 | * @return holder
79 | */
80 | public abstract RecyclerView.ViewHolder onFooterCreateViewHolder(ViewGroup parent, int viewType);
81 |
82 | /**
83 | * 绑定Header
84 | *
85 | * @param holder holder
86 | * @param position position 0~MAX_HEADER_SIZE
87 | */
88 | public abstract void onHeaderBindViewHolder(RecyclerView.ViewHolder holder, int position);
89 |
90 | /**
91 | * 绑定Footer
92 | *
93 | * @param holder holder
94 | * @param position position 0~MAX_FOOTER_SIZE
95 | */
96 | public abstract void onFooterBindViewHolder(RecyclerView.ViewHolder holder, int position);
97 |
98 | protected int childItemCount() {
99 | return childAdapter == null ? 0 : childAdapter.getItemCount();
100 | }
101 |
102 | protected RecyclerView.Adapter childAdapter() {
103 | return childAdapter;
104 | }
105 |
106 |
107 | @Override
108 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
109 | RecyclerView.ViewHolder holder;
110 | if (viewType >= TYPE_HEADER_START) {
111 | holder = onHeaderCreateViewHolder(parent, viewType - TYPE_HEADER_START);
112 | } else if (viewType <= TYPE_FOOTER_START + MAX_FOOTER_SIZE) {
113 | holder = onFooterCreateViewHolder(parent, viewType - TYPE_FOOTER_START);
114 | } else {
115 | holder = childAdapter.onCreateViewHolder(parent, viewType);
116 | }
117 | return holder;
118 | }
119 |
120 | @Override
121 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
122 | int headerPosition = headerCount();
123 | if (position < headerPosition) {
124 | setStaggeredLayoutParams(holder);
125 | onHeaderBindViewHolder(holder, position);
126 | } else {
127 | int childPosition = headerPosition + childItemCount();
128 | if (position < childPosition) {
129 | childAdapter.onBindViewHolder(holder, position - headerPosition);
130 | } else {
131 | setStaggeredLayoutParams(holder);
132 | onFooterBindViewHolder(holder, position - childPosition);
133 | }
134 | }
135 | }
136 |
137 | @Override
138 | public int getItemCount() {
139 | return headerCount() + childItemCount() + footerCount();
140 | }
141 |
142 | @Override
143 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position, List