Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AndroidJetpack概要 &旧AACの紹介

AndroidJetpack概要 &旧AACの紹介

katsuki-nakatani

June 14, 2018
Tweet

More Decks by katsuki-nakatani

Other Decks in Technology

Transcript

  1. 実装してみよう dependencies { def lifecycle_version = "1.1.1" // ViewModel and

    LiveData implementation "android.arch.lifecycle:extensions:$lifecycle_version" // alternatively - just ViewModel implementation "android.arch.lifecycle:viewmodel:$lifecycle_version" // use -ktx for Kotlin ※後述のViewModelを使うときに追加します // alternatively - just LiveData implementation "android.arch.lifecycle:livedata:$lifecycle_version" // alternatively - Lifecycles only (no ViewModel or LiveData). // Support library depends on this lightweight import implementation "android.arch.lifecycle:runtime:$lifecycle_version" annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version" // alternately - if using Java8, use the following instead of compiler implementation "android.arch.lifecycle:common-java8:$lifecycle_version" // optional - ReactiveStreams support for LiveData implementation "android.arch.lifecycle:reactivestreams:$lifecycle_version" // optional - Test helpers for LiveData testImplementation "android.arch.core:core-testing:$lifecycle_version" }
  2. LiveDataを使用する class MainActivity : AppCompatActivity() { val viewModel: MainViewModel =

    MainViewModel() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main_activity) viewModel.counter.observe(this, Observer { findViewById<TextView>(R.id.text_hello).setText("counter :" + it) }) findViewById<View>(R.id.button).setOnClickListener({ viewModel.countUp() }) } } MainActivity.kt class MainViewModel { val counter: MutableLiveData<Int> = MutableLiveData() init { counter.postValue(0) } fun countUp() { counter.postValue(counter.value?.plus(1)) } } MainViewModel.kt
  3. データバインディングを使用する場合 class MainActivity : AppCompatActivity() { val viewModel: MainViewModel =

    MainViewModel() lateinit var databinding:MainActivityBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) databinding = DataBindingUtil.setContentView(this,R.layout.main_activity) databinding.viewModel = viewModel databinding.setLifecycleOwner(this) databinding.button.setOnClickListener({ viewModel.countUp() }) } } MainActivity.kt class MainViewModel { var counterText:MutableLiveData<String> = MutableLiveData() var counter = 0 init { counter.postValue(0) } fun countUp() { counterText.postValue("count" + counter) counter++ } } MainViewModel.kt android.databinding.enableV2=true gradle.properties <Button android:id="@+id/button" android:layout_width="wrap_content" android:text="@{viewModel.counterText}" android:layout_height="wrap_content" /> main_activity.xml
  4. RecyclerViewの利用 class SampleListAdapter(internal val context: Context) :                 ListAdapter<String, SampleListAdapter.ViewHolder>(SampleListAdapter.DIFF_CALLBACK)

    { private var inflater: LayoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { var binding: ViewDataBinding = DataBindingUtil.bind(itemView)!! } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = inflater.inflate(R.layout.sample_list, parent, false) return ViewHolder(view) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { holder.binding.setVariable(BR.text, getItem(position)) } companion object { val DIFF_CALLBACK = object : DiffUtil.ItemCallback<String>() { override fun areItemsTheSame(old: String, new: String): Boolean { return TextUtils.equals(old,new) } override fun areContentsTheSame(old: String, new: String): Boolean { return TextUtils.equals(old,new) } } } } SampleAdapter.kt lateinit var sampleListAdapter: SampleListAdapter override fun onCreate(savedInstanceState: Bundle?) { sampleListAdapter = SampleListAdapter(this) databinding.recyclerView.layoutManager = LinearLayoutManager(this) databinding.recyclerView.adapter = sampleListAdapter viewModel.sampleList.observe(this, Observer { sampleListAdapter.submitList(it) }) findViewById<View>(R.id.button).setOnClickListener({ viewModel.addList() }) } class MainViewModel { var counter: Int = 0 val sampleList: MutableLiveData<List<String>> = MutableLiveData() init { sampleList.postValue(arrayListOf()) } fun addList() { sampleList.postValue( IntProgression.fromClosedRange(0,counter,1).map { it -> "text" + it }.toList()) counter++ } } SampleActivity.kt MainViewModel.kt
  5. ViewModelの実装 class MainViewModel : ViewModel() { MainViewModel.kt lateinit var viewModel:

    MainViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java) MainActivity.kt
  6. DemoCode override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) database = Room.databaseBuilder(applicationContext,AppDatabase::class.java,"sample.db")

    .build() databinding = DataBindingUtil.setContentView(this, R.layout.main_activity) databinding.setLifecycleOwner(this) viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java) databinding.viewModel = viewModel viewModel.find(database) userListAdapter = UserListAdapter(this) databinding.recyclerView.layoutManager = LinearLayoutManager(this) databinding.recyclerView.adapter = userListAdapter viewModel.userList.observe(this, Observer { Log.d("test","fire observe") userListAdapter.submitList(it) }) } class MainViewModel : ViewModel() { var userList: MutableLiveData<List<User>> = MutableLiveData() var progress = ObservableBoolean(false) fun find(appDatabase: AppDatabase) { if(userList.value == null) { Log.d("test", "findStart") progress.set(true) appDatabase.userDao().queryEnabledUser() .subscribeOn(Schedulers.computation()) .subscribe({ it -> Thread.sleep(3000) Log.d("test", "postValue") userList.postValue(it) progress.set(false) }) } } } MainViewModel.kt MainActivity.kt
  7. Demoログ 2018-06-14 10:01:44.591 29550-29550/com.gdgkobe.samplejetpack D/test: findStart 2018-06-14 10:01:44.597 29550-29550/com.gdgkobe.samplejetpack D/test:

    onStart 2018-06-14 10:01:47.679 29550-29645/com.gdgkobe.samplejetpack D/test: postValue 2018-06-14 10:01:47.679 29550-29550/com.gdgkobe.samplejetpack D/test: fire observe 2018-06-14 10:01:49.819 29550-29550/com.gdgkobe.samplejetpack D/test: onStop 2018-06-14 10:01:51.621 29550-29550/com.gdgkobe.samplejetpack D/test: findStart 2018-06-14 10:01:51.631 29550-29550/com.gdgkobe.samplejetpack D/test: onStart 2018-06-14 10:01:53.104 29550-29550/com.gdgkobe.samplejetpack D/test: onStop 2018-06-14 10:01:54.697 29550-29590/com.gdgkobe.samplejetpack D/test: postValue 2018-06-14 10:01:59.616 29550-29550/com.gdgkobe.samplejetpack D/test: onStart 2018-06-14 10:01:59.620 29550-29550/com.gdgkobe.samplejetpack D/test: fire observe
  8. build.gradle追加 dependencies { def room_version = "1.1.0" // or, for

    latest rc, use "1.1.1-rc1" implementation "android.arch.persistence.room:runtime:$room_version" annotationProcessor "android.arch.persistence.room:compiler:$room_version" // optional - RxJava support for Room implementation "android.arch.persistence.room:rxjava2:$room_version" // optional - Guava support for Room, including Optional and ListenableFuture implementation "android.arch.persistence.room:guava:$room_version" // Test helpers testImplementation "android.arch.persistence.room:testing:$room_version" } https://developer.android.com/topic/libraries/architecture/adding-components#room
  9. Entityクラスを作成 @Entity(tableName = "user") data class User( @PrimaryKey(autoGenerate = true)

    val id: Long, var firstName: String, var lastName: String, var enable: Boolean = false) { }
  10. Daoを作成 @Dao interface UserDao { @Insert(onConflict = OnConflictStrategy.REPLACE) fun insertUsers(vararg

    users: User) @Update fun updateUsers(vararg users: User) @Delete fun deleteUsers(vararg uses:User) @Query("select * from user") fun queryEnabledUser() : LiveData<List<User>> }
  11. あとは使うだけ class MainActivity : AppCompatActivity() { lateinit var userList:LiveData<List<User>> override

    fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) userList = Room.databaseBuilder(applicationContext,AppDatabase::class.java,"sample.db") .build() .userDao() .queryEnabledUser() } } java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time. at android.arch.persistence.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:204) .allowMainThreadQueries()
  12. 別スレッド処理を簡単にしたい dependencies { def room_version = "1.1.0" // or, for

    latest rc, use "1.1.1-rc1" // optional - RxJava support for Room implementation "android.arch.persistence.room:rxjava2:$room_version" } @Dao interface UserDao { @Query("select * from user") fun queryEnabledUser() : Single<List<User>> } fun find(appDatabase: AppDatabase) { appDatabase.userDao().queryEnabledUser() .subscribeOn(Schedulers.computation()) .subscribe({ it -> userList.postValue(it) }) }
  13. トランザクションを扱いたい Single.fromCallable({ appDatabase.runInTransaction { appDatabase.userDao().updateUsers(User(10, "FirstCC", "Last" + counter, true))

    appDatabase.userDao().insertUsers(User(10, "First", "Last" + counter, true)) } } ).subscribeOn(Schedulers.computation()) .subscribe({ it -> counter++ find(appDatabase) }, { e -> Log.e("test", e.message) }) @Insert(onConflict = OnConflictStrategy.ABORT) fun insertUsers(vararg users: User) @Update fun updateUsers(vararg users: User)
  14. RoomのQuery例 @Dao interface UserDao { } @Query("select * from user")

    fun queryEnabledUserLive() : LiveData<List<User>> @Query("select * from user") fun queryEnabledUser() : List<User> @Query("SELECT * FROM user WHERE id = :id") fun queryGet(id:Long) : Maybe<User> @Query("SELECT MAX(id) FROM user ") fun queryMaxUserId() : Long?