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

GUIアプリケーションの構造と設計

cockscomb
October 31, 2017

 GUIアプリケーションの構造と設計

Presented at Hatena Engineer Seminar #9

https://hatena.connpass.com/event/69844/

cockscomb

October 31, 2017
Tweet

More Decks by cockscomb

Other Decks in Programming

Transcript

  1. %BUB#JOEJOH <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <import type="jp.ne.hatena.myapplication.entry.Entry"/> <variable name="entry" type="Entry"/> </data>

    <android.support.constraint.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/titleView" android:text="@{entry.title}" .../> <TextView android:id="@+id/bodyView" android:text="@{entry.body}" .../> ... </android.support.constraint.ConstraintLayout> </layout>
  2. %BUB#JOEJOH class EntryViewHolder(private val binding: EntryItemBinding): RecyclerView.ViewHolder(binding.root) { companion object

    { fun create(parent: ViewGroup) = EntryViewHolder( EntryItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) ) } fun bindTo(entry: Entry?) { binding.entry = entry } }
  3. 3PPN @Entity(tableName = "entry", indices = arrayOf( Index(value = "date")

    )) data class Entry( @PrimaryKey(autoGenerate = true) val id: Int = 0, val title: String, val body: String, val date: Date )
  4. 3PPN @Dao interface EntryDao { @Insert fun insertEntry(entry: Entry) @Update

    fun updateEntry(entry: Entry) @Delete fun deleteEntry(entry: Entry) @Query("SELECT * FROM entry ORDER BY date DESC") fun entriesByDate(): Flowable<List<Entry>> // RxJava 2 }
  5. 3PPN @Dao interface EntryDao { @Insert fun insertEntry(entry: Entry) @Update

    fun updateEntry(entry: Entry) @Delete fun deleteEntry(entry: Entry) @Query("SELECT * FROM entry ORDER BY date DESC") fun entriesByDate(): LiveData<List<Entry>> // LiveData }
  6. 3PPN @Dao interface EntryDao { @Insert fun insertEntry(entry: Entry) @Update

    fun updateEntry(entry: Entry) @Delete fun deleteEntry(entry: Entry) @Query("SELECT * FROM entry ORDER BY date DESC") fun entriesByDate(): LivePagedListProvider<Int, Entry> // Paging Library }
  7. 3PPN class EntriesViewModel @Inject constructor(entryDao: EntryDao): ViewModel() { val entries:

    LiveData<PagedList<Entry>> = entryDao.entriesByDate().create(0, 50) } class EntriesAdapter: PagedListAdapter<Entry, EntryViewHolder>(EntryDiffCallback()) { override fun onBindViewHolder(holder: EntryViewHolder?, position: Int) { val entry = getItem(position) holder?.bindTo(entry) } ... } val entriesAdapter = EntriesAdapter() viewModel.entries.observe(this, Observer { list -> entriesAdapter.setList(list) }) recyclerView.adapter = entriesAdapter
  8. 3FBDUJWF1SPHSBNNJOH w 3Y+BWB "OESPJE  w -JWF%BUB "OESPJE  w

    3Y4XJGU J04  w 3FBDUJWF$PDPB J04  w 3Y+4 8FC
  9. 3Y+BWB fun createEntry(title: String, body: String) = Completable.create { emitter

    -> val entry = Entry(title = title, body = body, date = Date()) // Slow entryDao.insertEntry(entry) emitter.onComplete() }
  10. %BHHFS class App: Application(), HasActivityInjector { @Inject lateinit var activityInjector:

    DispatchingAndroidInjector<Activity> private fun applicationInjector() = DaggerAppComponent.builder() .app(this) .build() override fun onCreate() { super.onCreate() applicationInjector().inject(this) } override fun activityInjector() = activityInjector }
  11. %BHHFS @Singleton @Component(modules = arrayOf( AndroidSupportInjectionModule::class, AppModule::class, DatabaseModule::class, ActivityBuilder::class ))

    interface AppComponent { @Component.Builder interface Builder { @BindsInstance fun app(app: App): Builder fun build(): AppComponent } fun inject(app: App) }
  12. %BHHFS @Module abstract class AppModule { @Binds abstract fun bindsContext(app:

    App): Context } @Module abstract class ActivityBuilder { @ContributesAndroidInjector abstract fun contributesMainActivity(): MainActivity } @Module object DatabaseModule { @JvmStatic @Singleton @Provides fun providesAppDatabase(context: Context): Database = Room.databaseBuilder(context, Database::class.java, "diary_db").build() @JvmStatic @Provides fun providesEntryDao(database: Database) = database.entryDao() }
  13. %BHHFS class MainActivity : AppCompatActivity() { @Inject lateinit var entryDao:

    EntryDao ... override fun onCreate(savedInstanceState: Bundle?) { AndroidInjection.inject(this) super.onCreate(savedInstanceState) ... } ... }
  14. 3Y+BWB val compositeDisposable = CompositeDisposable() fun createEntry(title: String, body: String)

    = Completable.create { emitter -> val entry = Entry(title = title, body = body, date = Date()) entryDao.insertEntry(entry) emitter.onComplete() } fun create() { val disposable = createEntry( "ࠓ೔ͷ೔ه", "ࠓ೔ͷ൩͝൧͸ϋϯόʔάͩͬͨɻ͓͍͔ͬͨ͠ɻ") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe() compositeDisposable.add(disposable) }
  15. "DUJWJUZ 'SBHNFOU 'SBHNFOU "QQMJDBUJPO "QQ
 $PNQPOFOU "QQ.PEVMF 7JFX.PEFM %BHHFS 3Y+BWB

    "SDIJUFDUVSF $PNQPOFOUT 0UIFS
 .PEFMT 7JFX 7JFX %BUB#JOEJOH "DUJWJUZ
 $PNQPOFOU "DUJWJUZ.PE