Android Architecture Components 勉強会 #3
https://gdg-tokyo.connpass.com/event/79370/
https://speakerdeck.com/wasabeef/viewmodel-of-aac
Empty Activityで新しいKotlinプロジェクトを作ろう
※(パッケージ名はcom.sample.viewmodelを想定)
apply plugin: 'kotlin-kapt'
// ...
dependencies {
implementation "com.android.support:appcompat-v7:27.0.2"
// ...
implementation "android.arch.lifecycle:extensions:1.1.0"
kapt "android.arch.lifecycle:compiler:1.1.0"
}
ViewModelを継承したUserViewModelに書き換えよう
class UserViewModel {
private var user: User? = null
fun getUser(): User? {
if (user == null) {
load()
}
return user
}
private fun load() {
user = User("Hanyu", 23)
}
}
data class User(val name: String, val age: Int)
課題1の答え
data class User(val name: String, val age: Int)
class UserViewModel : ViewModel() {
private var user: MutableLiveData<User>? = null
fun getUser() {
if (user == null) {
user = MutableLiveData()
load()
}
return user
}
private fun load() {
// ...
}
}
継承したUserViewModelをActivity内で使ってみよう
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val user = UserViewModel()
Log.d("OLYMPICS", user.getUser()?.toString())
}
}
課題1-2の答え
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val user = ViewModelProviders.of(this).get(UserViewModel::class.java)
user.getUser()?.observe(this, Observer {
Log.d(“OLYMPICS", it?.toString())
})
}
}
Fragment内でuserA/B/Cが同じか確認しよう
class DogFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val userA = ViewModelProviders.of(this).get(UserViewModel::class.java)
val userB = ViewModelProviders.of(activity!!).get(UserViewModel::class.java)
val userC = ViewModelProviders.of(this).get(UserViewModel::class.java)
}
}
課題2の答え
userAとuserCは同一のFragment のViewModel (ViewModelStore)を参照するので一緒
userBはActivityのViewModel(ViewModelStore)を参照するのでuserA/userBとは違う
2つのFragment内でuserが同じか確認しよう
class TopFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val user = ViewModelProviders.of(this).get(UserViewModel::class.java)
}
}
class BottomFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val user = ViewModelProviders.of(this).get(UserViewModel::class.java)
}
}
課題3の答え
`of(this)` の指定はそれぞれのFragmentクラスを指定しているため別になる
`of(activity!!)` とすれば一緒になる
まずはactivity_main.xmlなどでFragmentを追加するためのFrameLayoutを作る
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.sample.viewmodel.myapplication.MainActivity"
>
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<FrameLayout
android:id="@+id/fragment_top"
android:background="@android:color/black"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toTopOf="@+id/textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
</android.support.constraint.ConstraintLayout>
MainActivity内で以下のJava/Kotlinを呼び追加する
getSupportFragmentManager().beginTransaction().add(R.id.fragment_top, new TopFragment())
supportFragmentManager.beginTransaction().add(R.id.fragment_bottom, BottomFragment())