├── .idea └── vcs.xml ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── spartons │ │ └── livedataexample │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── spartons │ │ │ └── livedataexample │ │ │ ├── LiveDataExample.kt │ │ │ ├── LiveDataMapExample.kt │ │ │ ├── LiveDataSwitchMapExample.kt │ │ │ ├── MainActivity.kt │ │ │ ├── User.kt │ │ │ ├── UserAdapter.kt │ │ │ └── UserRepo.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── live_data_example.xml │ │ ├── live_data_map_example.xml │ │ ├── live_data_swicth_map_example.xml │ │ └── users_list.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.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 │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── spartons │ └── livedataexample │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ └── gradle-wrapper.properties └── settings.gradle /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | 5 | android { 6 | compileSdkVersion 27 7 | defaultConfig { 8 | applicationId "com.spartons.livedataexample" 9 | minSdkVersion 20 10 | targetSdkVersion 27 11 | versionCode 1 12 | versionName "1.0" 13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | } 22 | 23 | dependencies { 24 | implementation fileTree(dir: 'libs', include: ['*.jar']) 25 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 26 | implementation 'com.android.support:appcompat-v7:27.1.1' 27 | implementation 'com.android.support:design:27.1.1' 28 | implementation 'com.android.support:recyclerview-v7:27.1.1' 29 | implementation 'com.android.support.constraint:constraint-layout:1.1.2' 30 | implementation 'android.arch.lifecycle:viewmodel:1.1.1' 31 | implementation "android.arch.lifecycle:extensions:1.1.1" 32 | implementation 'io.reactivex.rxjava2:rxjava:2.1.8' 33 | annotationProcessor 'android.arch.lifecycle:compiler:1.1.1' 34 | implementation 'android.arch.work:work-runtime:1.0.0-alpha04' 35 | testImplementation 'junit:junit:4.12' 36 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 37 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 38 | } 39 | -------------------------------------------------------------------------------- /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 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/spartons/livedataexample/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.spartons.livedataexample 2 | 3 | import android.support.test.InstrumentationRegistry 4 | import android.support.test.runner.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getTargetContext() 22 | assertEquals("com.spartons.livedataexample", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 24 | 25 | 29 | 30 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/spartons/livedataexample/LiveDataExample.kt: -------------------------------------------------------------------------------- 1 | package com.spartons.livedataexample 2 | 3 | import android.arch.lifecycle.MutableLiveData 4 | import android.arch.lifecycle.Observer 5 | import android.arch.lifecycle.ViewModel 6 | import android.arch.lifecycle.ViewModelProviders 7 | import android.content.Context 8 | import android.content.Intent 9 | import android.os.Bundle 10 | import android.support.v7.app.AppCompatActivity 11 | import android.util.Log 12 | import io.reactivex.Observable 13 | import kotlinx.android.synthetic.main.live_data_example.* 14 | import java.util.* 15 | import java.util.concurrent.TimeUnit 16 | 17 | class LiveDataExample : AppCompatActivity() { 18 | 19 | companion object { 20 | fun getLiveData(callingClassContext: Context) = Intent(callingClassContext, LiveDataExample::class.java) 21 | } 22 | 23 | override fun onCreate(savedInstanceState: Bundle?) { 24 | super.onCreate(savedInstanceState) 25 | setContentView(R.layout.live_data_example) 26 | val timeChangerViewModel = ViewModelProviders.of(this).get(TimeChangerViewModel::class.java) 27 | val calendar = Calendar.getInstance() 28 | timeChangerViewModel.timerValue.observe(this, Observer { t -> 29 | calendar?.timeInMillis = t!! 30 | timTextView.text = calendar.time.toString() 31 | }) 32 | } 33 | } 34 | 35 | class TimeChangerViewModel : ViewModel() { 36 | 37 | val timerValue = MutableLiveData() 38 | 39 | init { 40 | Log.e("Model", "initialize") 41 | timerValue.value = System.currentTimeMillis() 42 | startTimer() 43 | } 44 | 45 | private fun startTimer() { 46 | Observable.interval(2, 2, TimeUnit.SECONDS) 47 | .subscribe({ 48 | Log.e("Model", it.toString()) 49 | timerValue.postValue(System.currentTimeMillis()) 50 | }, Throwable::printStackTrace) 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /app/src/main/java/com/spartons/livedataexample/LiveDataMapExample.kt: -------------------------------------------------------------------------------- 1 | package com.spartons.livedataexample 2 | 3 | import android.arch.lifecycle.* 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.os.Bundle 7 | import android.support.design.widget.Snackbar 8 | import android.support.v7.app.AppCompatActivity 9 | import kotlinx.android.synthetic.main.live_data_example.* 10 | import kotlinx.android.synthetic.main.live_data_map_example.* 11 | 12 | class LiveDataMapExample : AppCompatActivity() { 13 | 14 | companion object { 15 | fun getMapLiveData(callingClassContext: Context) = Intent(callingClassContext, LiveDataMapExample::class.java) 16 | } 17 | 18 | override fun onCreate(savedInstanceState: Bundle?) { 19 | super.onCreate(savedInstanceState) 20 | setContentView(R.layout.live_data_map_example) 21 | val viewModel = ViewModelProviders.of(this).get(TransformationViewModel::class.java) 22 | viewModel.userAddedData.observe(this, Observer { t -> Snackbar.make(mapActivityRootView, t!!, Snackbar.LENGTH_SHORT).show() }) 23 | addUserButton.setOnClickListener { 24 | viewModel.addNewUser(User(addNewEditText.text.toString())) 25 | } 26 | } 27 | } 28 | 29 | class TransformationViewModel : ViewModel() { 30 | 31 | private val userLiveData = MutableLiveData() 32 | 33 | val userAddedData: LiveData = Transformations.map(userLiveData, ::someFunc) 34 | 35 | private fun someFunc(user: User) = "New user ${user.username} added to database!" 36 | 37 | fun addNewUser(user: User) = apply { userLiveData.value = user } 38 | } -------------------------------------------------------------------------------- /app/src/main/java/com/spartons/livedataexample/LiveDataSwitchMapExample.kt: -------------------------------------------------------------------------------- 1 | package com.spartons.livedataexample 2 | 3 | import android.arch.lifecycle.* 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.os.Bundle 7 | import android.support.v7.app.AppCompatActivity 8 | import android.support.v7.widget.LinearLayoutManager 9 | import kotlinx.android.synthetic.main.live_data_swicth_map_example.* 10 | 11 | class LiveDataSwitchMapExample : AppCompatActivity() { 12 | 13 | companion object { 14 | fun getSwitchMapLiveData(callingClassContext: Context) = Intent(callingClassContext, LiveDataSwitchMapExample::class.java) 15 | } 16 | 17 | private val userList: MutableList = ArrayList() 18 | private lateinit var userAdapter: UserAdapter 19 | 20 | override fun onCreate(savedInstanceState: Bundle?) { 21 | super.onCreate(savedInstanceState) 22 | setContentView(R.layout.live_data_swicth_map_example) 23 | userRecyclerView.layoutManager = LinearLayoutManager(this) 24 | userRecyclerView.setHasFixedSize(true) 25 | userAdapter = UserAdapter(this, userList) 26 | userRecyclerView.adapter = userAdapter 27 | val viewModel = ViewModelProviders.of(this).get(UserViewModel::class.java) 28 | addUserButton.setOnClickListener { viewModel.searchUserByName(addNewEditText.text.toString()) } 29 | viewModel.userNameResult.observe(this, Observer { 30 | if (userList.isNotEmpty()) 31 | userList.clear() 32 | userList.addAll(it!!) 33 | userAdapter.notifyDataSetChanged() 34 | }) 35 | } 36 | } 37 | 38 | class UserViewModel : ViewModel() { 39 | 40 | private val query = MutableLiveData() 41 | private val userRepo = UserRepo() 42 | 43 | val userNameResult: LiveData> = Transformations.switchMap( 44 | query, 45 | ::temp 46 | ) 47 | 48 | private fun temp(name: String) = userRepo.searchUserWithName(name) 49 | 50 | fun searchUserByName(name: String) = apply { query.value = name } 51 | } -------------------------------------------------------------------------------- /app/src/main/java/com/spartons/livedataexample/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.spartons.livedataexample 2 | 3 | import android.support.v7.app.AppCompatActivity 4 | import android.os.Bundle 5 | import kotlinx.android.synthetic.main.activity_main.* 6 | 7 | class MainActivity : AppCompatActivity() { 8 | 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | setContentView(R.layout.activity_main) 12 | liveDataExampleButton.setOnClickListener { startActivity(LiveDataExample.getLiveData(this)) } 13 | liveDataMapExampleButton.setOnClickListener { startActivity(LiveDataMapExample.getMapLiveData(this)) } 14 | liveDataSwitchMapExampleButton.setOnClickListener { startActivity(LiveDataSwitchMapExample.getSwitchMapLiveData(this)) } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/spartons/livedataexample/User.kt: -------------------------------------------------------------------------------- 1 | package com.spartons.livedataexample 2 | 3 | data class User(val username: String) -------------------------------------------------------------------------------- /app/src/main/java/com/spartons/livedataexample/UserAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.spartons.livedataexample 2 | 3 | import android.content.Context 4 | import android.support.v7.widget.RecyclerView 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import android.widget.TextView 9 | 10 | class UserAdapter(context: Context, private val userList: List) : RecyclerView.Adapter() { 11 | 12 | private val layoutInflater = LayoutInflater.from(context) 13 | 14 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder { 15 | return UserViewHolder(layoutInflater.inflate(R.layout.users_list, parent, false)) 16 | } 17 | 18 | override fun getItemCount() = userList.size 19 | 20 | override fun onBindViewHolder(holder: UserViewHolder, position: Int) { 21 | val user = userList[position] 22 | holder.userNameTextView.text = user.username 23 | } 24 | } 25 | 26 | class UserViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { 27 | 28 | val userNameTextView: TextView = itemView.findViewById(R.id.userNameTextView) 29 | } -------------------------------------------------------------------------------- /app/src/main/java/com/spartons/livedataexample/UserRepo.kt: -------------------------------------------------------------------------------- 1 | package com.spartons.livedataexample 2 | 3 | import android.arch.lifecycle.LiveData 4 | import android.arch.lifecycle.MutableLiveData 5 | 6 | class UserRepo { 7 | 8 | private val userList: MutableList = ArrayList() 9 | 10 | init { 11 | for (i in 1..100) 12 | userList.add(User("Hello user $i")) 13 | } 14 | 15 | fun searchUserWithName(name: String): LiveData> { 16 | val searchUserList = ArrayList() 17 | for (user in userList) 18 | if (user.username.contains(regex = Regex(name))) 19 | searchUserList.add(user) 20 | val temp = MutableLiveData>() 21 | temp.value = searchUserList 22 | return temp 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 |