├── app ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── values │ │ │ ├── dimen.xml │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ ├── layout │ │ │ ├── other_fragment.xml │ │ │ ├── carousel.xml │ │ │ ├── card.xml │ │ │ ├── example_activity.xml │ │ │ ├── banner.xml │ │ │ └── main_fragment.xml │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ └── drawable │ │ │ └── ic_launcher_background.xml │ │ ├── java │ │ └── br │ │ │ └── com │ │ │ └── nestedrecyclerviewstate │ │ │ ├── Content.kt │ │ │ ├── staterestoration │ │ │ ├── NestedRecyclerViewViewHolder.kt │ │ │ └── NestedRecyclerViewStateRecoverAdapter.kt │ │ │ ├── OtherFragment.kt │ │ │ ├── ExampleActivity.kt │ │ │ ├── MainViewModel.kt │ │ │ ├── MainFragment.kt │ │ │ ├── CarouselAdapter.kt │ │ │ └── ContentAdapter.kt │ │ └── AndroidManifest.xml ├── proguard-rules.pro └── build.gradle ├── .idea ├── .name ├── .gitignore ├── codeStyles │ ├── codeStyleConfig.xml │ └── Project.xml ├── compiler.xml ├── misc.xml └── jarRepositories.xml ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── README.md ├── gradle.properties ├── .gitignore ├── gradlew.bat └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | NestedRecyclerViewState -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | rootProject.name = "NestedRecyclerViewState" -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmorigaki/nested-recycler-view-state-study/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/values/dimen.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10dp 4 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmorigaki/nested-recycler-view-state-study/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmorigaki/nested-recycler-view-state-study/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmorigaki/nested-recycler-view-state-study/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmorigaki/nested-recycler-view-state-study/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmorigaki/nested-recycler-view-state-study/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmorigaki/nested-recycler-view-state-study/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmorigaki/nested-recycler-view-state-study/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmorigaki/nested-recycler-view-state-study/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmorigaki/nested-recycler-view-state-study/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmorigaki/nested-recycler-view-state-study/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/java/br/com/nestedrecyclerviewstate/Content.kt: -------------------------------------------------------------------------------- 1 | package br.com.nestedrecyclerviewstate 2 | 3 | sealed class Content(val id: String) { 4 | class Banner(id: String) : Content(id) 5 | class Carousel(id: String, val list: List) : Content(id) 6 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Jan 21 18:27:48 BRT 2021 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nested RecyclerView state 2 | This repository contains an example related to the problem and solution to restore the state of nested RecyclerViews 3 | 4 | ## Article 5 | 6 | Detailed information about the problem and the solution can be found [here](https://medium.com/@cesarmorigaki) 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #6200EE 4 | #3700B3 5 | #03DAC5 6 | #CCCCCC 7 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/java/br/com/nestedrecyclerviewstate/staterestoration/NestedRecyclerViewViewHolder.kt: -------------------------------------------------------------------------------- 1 | package br.com.nestedrecyclerviewstate.staterestoration 2 | 3 | import androidx.recyclerview.widget.RecyclerView 4 | 5 | interface NestedRecyclerViewViewHolder { 6 | fun getId(): String 7 | fun getLayoutManager(): RecyclerView.LayoutManager? 8 | } -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | NestedRecyclerViewState 3 | Banner %1$s 4 | Open fragment 5 | Other fragment 6 | Back button pressed 7 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/other_fragment.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/carousel.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/card.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/layout/example_activity.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/layout/banner.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | -------------------------------------------------------------------------------- /app/src/main/java/br/com/nestedrecyclerviewstate/OtherFragment.kt: -------------------------------------------------------------------------------- 1 | package br.com.nestedrecyclerviewstate 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import androidx.fragment.app.Fragment 8 | import br.com.nestedrecyclerviewstate.databinding.OtherFragmentBinding 9 | 10 | class OtherFragment : Fragment() { 11 | override fun onCreateView( 12 | inflater: LayoutInflater, 13 | container: ViewGroup?, 14 | savedInstanceState: Bundle? 15 | ): View { 16 | return OtherFragmentBinding.inflate(layoutInflater).root 17 | } 18 | 19 | companion object { 20 | fun newInstance() : Fragment { 21 | return OtherFragment() 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/br/com/nestedrecyclerviewstate/ExampleActivity.kt: -------------------------------------------------------------------------------- 1 | package br.com.nestedrecyclerviewstate 2 | 3 | import android.os.Bundle 4 | import android.widget.Toast 5 | import androidx.appcompat.app.AppCompatActivity 6 | import br.com.nestedrecyclerviewstate.databinding.ExampleActivityBinding 7 | 8 | class ExampleActivity : AppCompatActivity() { 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | ExampleActivityBinding.inflate(layoutInflater).apply { 12 | setContentView(root) 13 | supportFragmentManager.beginTransaction() 14 | .replace(R.id.container, MainFragment.newInstance()).commit() 15 | } 16 | } 17 | 18 | override fun onBackPressed() { 19 | super.onBackPressed() 20 | Toast.makeText(this, getString(R.string.back_pressed_message), Toast.LENGTH_SHORT).show() 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/java/br/com/nestedrecyclerviewstate/MainViewModel.kt: -------------------------------------------------------------------------------- 1 | package br.com.nestedrecyclerviewstate 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.lifecycle.MutableLiveData 5 | import androidx.lifecycle.ViewModel 6 | 7 | class MainViewModel : ViewModel() { 8 | private val _content = MutableLiveData>() 9 | val content : LiveData> = _content 10 | 11 | init { 12 | generateContent() 13 | } 14 | 15 | private fun generateContent() { 16 | val cards = listOf(1..8).flatten() 17 | _content.value = listOf( 18 | Content.Carousel("100", cards), 19 | Content.Banner("1"), 20 | Content.Carousel("101", cards), 21 | Content.Carousel("102", cards), 22 | Content.Carousel("103", cards), 23 | Content.Banner("2"), 24 | Content.Carousel("104", cards), 25 | Content.Carousel("105", cards), 26 | Content.Carousel("106", cards), 27 | Content.Banner("3"), 28 | ) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official -------------------------------------------------------------------------------- /app/src/main/res/layout/main_fragment.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 18 | 19 |