Skip to content

Instantly share code, notes, and snippets.

@wasabeef
Last active May 1, 2018 02:43
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save wasabeef/3b8fda5e04ec2c750f825b7e5b79565c to your computer and use it in GitHub Desktop.
Save wasabeef/3b8fda5e04ec2c750f825b7e5b79565c to your computer and use it in GitHub Desktop.
ViewModel - Android Architecture Components

ViewModel - Android Architecture Components

Android Architecture Components 勉強会 #3
https://gdg-tokyo.connpass.com/event/79370/

Slide

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内でFragmentを追加する

まずは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())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment