Android Studio 3.0ã§Androidã®éçºã®ãã¹ãŠãã«ããŒãããããžã§ã¯ããèŠã€ããã®ã¯éåžžã«é£ããã®ã§ãç§ã¯ãããæžãããšã«ããŸããã ãã®èšäºã§ã¯ã以äžãåæããŸãã
- Android Studio 3
- Kotlinããã°ã©ãã³ã°èšèª
- çµã¿ç«ãŠãªãã·ã§ã³
- å¶çŽã¬ã€ã¢ãŠã
- ããŒã¿ãã€ã³ãã£ã³ã°ã©ã€ãã©ãª
- MVVMã¢ãŒããã¯ãã£+ãªããžããªãã¿ãŒã³ïŒããããŒã䜿çšïŒ+ AndroidãããŒãžã£ãŒã©ãããŒ
- RxJava2ãšãããã¢ãŒããã¯ãã£ã§ã©ã®ããã«åœ¹ç«ã€ã
- Dagger 2.11ãäŸåæ§æ³šå ¥ãšã¯äœã§ããããªãããã䜿çšããå¿ èŠããããŸããã
- ã¬ãããã£ããïŒRx Java2ïŒ
- ã«ãŒã ïŒRx Java2ïŒ
ã¢ããªã±ãŒã·ã§ã³ã¯äœã«ãªããŸããïŒ
ç§ãã¡ã®ã¢ããªã±ãŒã·ã§ã³ã¯ãäžèšã®ãã¹ãŠãã«ããŒããæãåçŽãªã¢ããªã±ãŒã·ã§ã³ã§ããGitHubãããã¹ãŠã®googlesamplesãŠãŒã¶ãŒãªããžããªãæœåºãããã®ããŒã¿ãããŒã«ã«ããŒã¿ããŒã¹ã«ä¿åããŠãŠãŒã¶ãŒã«è¡šç€ºããé¢æ°ã1ã€ã ããããŸãã
ã§ããã ãå€ãã®ã³ãŒãè¡ã説æããããšããŸãã GitHubã«æçš¿ããã³ãŒãã¯ãã€ã§ã確èªã§ããŸã ã
Android Studio
Android Studio 3ãã€ã³ã¹ããŒã«ããã«ã¯ã ãã®ããŒãžã«ã¢ã¯ã»ã¹ããŠãã ãã
Android Studio 3ã¯KotlinããµããŒãããŠããŸãã Androidãããžã§ã¯ãã®äœæãéããŸã ã ããã«ã KotlinãµããŒããå«ããšããã©ãã«ã®æ°ãããã©ã°ã衚瀺ãããŸã ã ããã©ã«ãã§éžæãããŠããŸãã [ 次ãž]ã 2åã¯ãªãã¯ããŠ[ 空ã®ã¢ã¯ãã£ãã㣠]ãéžæãã[ å®äº ]ãã¯ãªãã¯ããŸãã
ããã§ãšãããããŸãïŒ Kotlinã§æåã®Androidã¢ããªãäœæããŸãã:)
ã³ããªã³
MainActivity.ktãèŠãããšãã§ããŸãïŒ
package me.fleka.modernandroidapp import android.support.v7.app.AppCompatActivity import android.os.Bundle class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } }
.ktæ¡åŒµåã¯ããã¡ã€ã«ãKotlinãã¡ã€ã«ã§ããããšãæå³ããŸãã
MainActivityïŒAppCompatActivityïŒïŒã¯ã AppCompatActivityãæ¡åŒµããããšãæå³ããŸãã
ããã«ããã¹ãŠã®ã¡ãœããã«ã¯ããŒã¯ãŒãfunãå¿ èŠã§ããKotlinã§ã¯ã䜿çšããå¿ èŠã¯ãããŸããã å¿ èŠã«å¿ããŠã§ããŸãã Javaã®ããã«ãã¢ãããŒã·ã§ã³ã§ã¯ãªãoverrideããŒã¯ãŒãã䜿çšããå¿ èŠããããŸã ã
ããã¯ã©ãããæå³ã§ããïŒ savedInstanceStateïŒBundleïŒ ïŒ ããã¯ãsavedInstanceStateãBundleåãŸãã¯nullåã§ããããšãæå³ããŸã ã Kotlin nullã¯å®å šãªèšèªã§ãã ããªããæã£ãŠããå ŽåïŒ
var a : String
aã¯åæåããå¿ èŠãããã nullã«ã¯ã§ããªããããã³ã³ãã€ã«ãšã©ãŒãçºçããŸã ã ã€ãŸãã次ã®ããã«æžãå¿ èŠããããŸãã
var a : String = "Init value"
ããã«ããããè¡ããšã³ã³ãã€ã«ãšã©ãŒãçºçããŸãã
a = null
NULLå¯èœã«ããã«ã¯ã次ã®ããã«èšè¿°ããå¿ èŠããããŸãã
var a : String?
ãããKotlinèšèªã®éèŠãªæ©èœãªã®ã¯ãªãã§ããïŒ ããã«ããã NPEãåé¿ã§ããŸãã Androidéçºè ã¯ãã§ã«NPEã«ããããããŠããŸãã nullã®äœæè ã§ããTony Hoar Evenã§ãããçºæã«å¯ŸããŠè¬çœªããŸããã null蚱容ã®nameTextViewããããšããŸãã å€æ°ãnullã®å Žåã次ã®ã³ãŒãã§NPEãååŸããŸãã
nameTextView.setEnabled(true)
ããããå®éã«ã¯ã³ããªã³ã¯è¯ãã§ãã圌ã¯ç§ãã¡ããããããããšããèš±ããªãã§ãããã æŒç®åã䜿çšããŸããïŒ ãŸãã¯æŒç®å!! ã æŒç®åã䜿çšããå¿ èŠããããŸããïŒ ïŒ
nameTextView?.setEnabled(true)
æååã¯ãnameTextViewãnullã§ãªãå Žåã«ã®ã¿å®è¡ãããŸãã ãã以å€ã®å ŽåãæŒç®åã䜿çšãããš!! ïŒ
nameTextView!!.setEnabled(true)
nameTextViewã nullã®å ŽåãNPEãååŸããŸãã ããã¯åéºå®¶åãã§ã:)ã
ããã¯Kotlinã®ç°¡åãªçŽ¹ä»ã§ãã ç¶è¡ãããšãKotlinã®å¥ã®ç¹å®ã®ã³ãŒãã®èª¬æãåæ¢ããŸãã
2.ããªã¢ã³ãã®äœæ
éçºã§ã¯ãå€ãã®å Žåç°ãªãç°å¢ããããŸãã æãæšæºçãªã®ã¯ã ãã¹ãããã³å®çšŒåç°å¢ã§ãã ãããã®ç°å¢ã¯ããµãŒããŒURLãã¢ã€ã³ã³ãååãå®å APIãªã©ãç°ãªãå ŽåããããŸãã åãããžã§ã¯ãã®flekaã«ã¯æ¬¡ã®ãã®ããããŸãã
- finalProductionãGooglePlayã¹ãã¢ã«åºè·ãããŸãã
- demoProduction ãã€ãŸãããŸã Google Playã¹ãã¢ã«ãªãæ°æ©èœãåããéçšãµãŒããŒã®URLãå«ãããŒãžã§ã³ã ã客æ§ã¯ããã®ããŒãžã§ã³ãGoogle Playã®é£ã«ã€ã³ã¹ããŒã«ããŠããã¹ãããŠãã£ãŒãããã¯ãæäŸã§ããŸãã
- demoTestingã¯ããã¹ããµãŒããŒURLã䜿çšããdemoProductionãšåãã§ãã
- éçºè ããã³ãã¶ã€ããŒãšããŠç§ã«åœ¹ç«ã€ã¢ã㯠ã æã ãæ¢è£œã®ãã¶ã€ã³ããããAPIã¯ãŸã æºåãã§ããŠããŸããã APIã®éçºãéå§ãããã®ãåŸ ã€ããšã¯è§£æ±ºçã§ã¯ãããŸããã ãã®ãã«ããªãã·ã§ã³ã«ã¯åœã®ããŒã¿ãä»å±ããŠãããããèšèšããŒã ã¯ããã確èªããŠãã£ãŒãããã¯ãæäŸã§ããŸãã ãããå éãããªãããšã¯éåžžã«äŸ¿å©ã§ãã APIã®æºåãã§ããããéçºãdemoTestingç°å¢ã«ç§»è¡ããŸãã
ãã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ãããããã¹ãŠã䜿çšããŸãã ãããã¯ç°ãªãapplicationIdãšååãæã¡ãŸãã Gradle 3.0.0ã«ã¯ã補åã®çš®é¡ãæ··åã§ããæ°ããflavorDimension APIããããŸããããšãã°ã demoãšminApi23ã®çš®é¡ãæ··åã§ããŸãã ãã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ããããã©ã«ããflavorDimensionã®ã¿ã䜿çšããŸãã ã¢ããªã±ãŒã·ã§ã³ã®build.gradleã«ç§»åãããã®ã³ãŒããandroid {}å ã«è²Œãä»ããŸã
flavorDimensions "default" productFlavors { finalProduction { dimension "default" applicationId "me.fleka.modernandroidapp" resValue "string", "app_name", "Modern App" } demoProduction { dimension "default" applicationId "me.fleka.modernandroidapp.demoproduction" resValue "string", "app_name", "Modern App Demo P" } demoTesting { dimension "default" applicationId "me.fleka.modernandroidapp.demotesting" resValue "string", "app_name", "Modern App Demo T" } mock { dimension "default" applicationId "me.fleka.modernandroidapp.mock" resValue "string", "app_name", "Modern App Mock" } }
競åãçºçããªãããã«ãstrings.xmlã«ç§»åããŠapp_nameè¡ãåé€ããŸãã 次ã«ã[ ä»ããåæ ]ãã¯ãªãã¯ããŸã ã ç»é¢ã®å·ŠåŽã«ããBuild Variantsã«ç§»åãããšã4ã€ã®ãã«ããªãã·ã§ã³ã衚瀺ãããŸããåãªãã·ã§ã³ã«ã¯ã DebugãšReleaseã® 2ã€ã®ãã«ãã¿ã€ãããããŸãã demoProductionãã«ããªãã·ã§ã³ã«ç§»åããŠå®è¡ããŸãã 次ã«ãå¥ã®ã¹ã€ããã«åãæ¿ããŠå®è¡ããŸãã ç°ãªãååã®2ã€ã®ã¢ããªã±ãŒã·ã§ã³ã衚瀺ãããŸãã
3. ConstraintLayout
activity_main.xmlãéããšããã®ã¬ã€ã¢ãŠããConstrainLayoutã§ããããšãããããŸãã iOSåãã®ã¢ããªãäœæããããšãããã°ã AutoLayoutã«ã€ããŠç¥ã£ãŠããŸã ã ConstraintLayoutã¯æ¬åœã«åœŒã®ããã«èŠããŸãã 圌ãã¯åããã¯ã€ããªã¢ã«ãŽãªãºã ã䜿çšããŸãã
<?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="me.fleka.modernandroidapp.MainActivity"> <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" /> </android.support.constraint.ConstraintLayout>
å¶çŽã¯ã ãã¥ãŒéã®é¢ä¿ãèšè¿°ããã®ã«åœ¹ç«ã¡ãŸã ã åViewã«ã¯ ãååŽã«1ã€ãã€ã4ã€ã®Constraintãå¿ èŠã§ãã ãã®å Žåã ãã¥ãŒã¯ååŽã®èŠªã«ãã£ãŠå¶éãããŸãã
[ ãã¶ã€ã³ ]ã¿ãã§TextViewã® ãHello Worldããå°ãäžã«ç§»åãããšã[ ããã¹ã ]ã¿ãã«æ°ããè¡ã衚瀺ãããŸãã
app:layout_constraintVertical_bias="0.28"
[ ãã¶ã€ã³]ã¿ããš[ ããã¹ã]ã¿ããåæãããŸãã [ ãã¶ã€ã³ ]ã¿ãã®å€æŽã¯ã[ ããã¹ã ]ã¿ãã®xmlã«åœ±é¿ãåãŒãããã®éãåæ§ã§ãã Vertical_biasã¯ã圌ã®Constraintã®åçŽãã¥ãŒãã¬ã³ãã瀺ããŸãã åçŽæ¹åã«äžå€®æãããå Žåã¯ã次ã䜿çšããŸãã
app:layout_constraintVertical_bias="0.28"
ã¢ã¯ãã£ããã£ã« 1ã€ã®ãªããžããªã®ã¿ã衚瀺ãããŸãããã ãªããžããªã®ååãæã®æ°ãææè ã衚瀺ããããªããžããªã«åé¡ããããã©ããã衚瀺ãããŸãã
ãã®ãããªã¬ã€ã¢ãŠããååŸããã«ã¯ãxmlã¯æ¬¡ã®ããã«ãªããŸãã
<?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="me.fleka.modernandroidapp.MainActivity"> <TextView android:id="@+id/repository_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="16dp" android:layout_marginStart="16dp" android:textSize="20sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.083" tools:text="Modern Android app" /> <TextView android:id="@+id/repository_has_issues" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="16dp" android:layout_marginStart="16dp" android:layout_marginTop="8dp" android:text="@string/has_issues" android:textStyle="bold" app:layout_constraintBottom_toBottomOf="@+id/repository_name" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="1.0" app:layout_constraintStart_toEndOf="@+id/repository_name" app:layout_constraintTop_toTopOf="@+id/repository_name" app:layout_constraintVertical_bias="1.0" /> <TextView android:id="@+id/repository_owner" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginEnd="16dp" android:layout_marginStart="16dp" android:layout_marginTop="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/repository_name" app:layout_constraintVertical_bias="0.0" tools:text="Mladen Rakonjac" /> <TextView android:id="@+id/number_of_starts" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginEnd="16dp" android:layout_marginStart="16dp" android:layout_marginTop="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="1" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/repository_owner" app:layout_constraintVertical_bias="0.0" tools:text="0 stars" /> </android.support.constraint.ConstraintLayout>
ããŒã«ã«ããŸãããïŒããã¹ãã¯æ°ã«ããŸããã ã¬ã€ã¢ãŠãã®è¯ããã¬ãã¥ãŒãèŠãã®ã«åœ¹ç«ã¡ãŸãã
ã¬ã€ã¢ãŠããå¹³åŠã§ããããšã«ãæ°ã¥ããããããŸããã ãã¹ããããã¬ã€ã¢ãŠãã¯ãããŸããã ãã¹ããããã¬ã€ã¢ãŠãã¯ãããã©ãŒãã³ã¹ã«åœ±é¿ãäžããå¯èœæ§ããããããã§ããã ã䜿çšããªãã§ãã ããã 詳现ã«ã€ããŠã¯ã ãã¡ããã芧ãã ãã ã ããã«ã ConstraintLayoutã¯ããŸããŸãªç»é¢ãµã€ãºã§ããŸãæ©èœããŸãã
ãããŠãç§ã¯åžæããçµæãéåžžã«è¿ éã«éæã§ããããã«æããŸãã
ããã¯ConstraintLayoutã®ç°¡åãªçŽ¹ä»ã§ããã Googleã³ãŒãã©ãã¯ãã¡ãããã ConstraintLayoutããã¥ã¡ã³ãã¯GitHubã«ãããŸã ã
4.ããŒã¿ãã€ã³ãã£ã³ã°ã©ã€ãã©ãª
ããŒã¿ãã€ã³ãã£ã³ã°ã©ã€ãã©ãªã«ã€ããŠèãããšããæåã«èªåãã質åã¯ãã ButterKnifeã¯éåžžã«ããŸãæ©èœããŸããããã«ãxmlããViewãååŸããã®ã«åœ¹ç«ã€ãã©ã°ã€ã³ã䜿çšããŠããŸãããããå€æŽããå¿ èŠãããã®ã¯ãªãã§ããïŒã ããŒã¿ãã€ã³ãã£ã³ã°ã«ã€ããŠè©³ããç¥ããšããã«ãæåã«ButterKnifeã䜿çšãããšããšåãæ°æã¡ã«ãªããŸããã
ButterKnifeã¯ã©ã®ããã«åœ¹ç«ã¡ãŸããïŒ
ButterKnifeã¯ãéå±ãªfindViewByIdãåãé€ãã®ã«åœ¹ç«ã¡ãŸãã ãããã£ãŠããã¥ãŒã5ã€ããå ŽåãButterknifeã䜿çšããªããšããã¥ãŒããã€ã³ããã5 + 5è¡ããããŸãã ButterKnifeã«ã¯5è¡ãããŸãã 以äžã§ãã
ButterKnifeã®äœãæªãã®ã§ããïŒ
ButterKnifeã¯ãŸã ã³ãŒããµããŒãã®åé¡ã解決ããŸããã ButterKnifeã䜿çšãããšãã«ãxmlã®Viewãåé€ããActivity / Fragmentã¯ã©ã¹ã®ãã€ã³ãã£ã³ã°ã³ãŒããåé€ããªãã£ããããå®è¡æã«äŸå€ãé »ç¹ã«çºçããŸããã ãŸããViewãxmlã«è¿œå ããå Žåã¯ãå床ãã€ã³ãããå¿ èŠããããŸãã ããã¯éåžžã«éå±ã§ãã ããªãã¯é£çµ¡ãåãåãæéãç¡é§ã«ããŠããã
ããŒã¿ãã€ã³ãã£ã³ã°ã©ã€ãã©ãªã¯ã©ãã§ããïŒ
å€ãã®å©ç¹ããããŸãïŒ ããŒã¿ãã€ã³ãã£ã³ã°ã©ã€ãã©ãªã䜿çšãããšãããã1è¡ã®ã³ãŒãã§ãã¥ãŒããã€ã³ãã§ããŸãã ãããã©ã®ããã«æ©èœãããããèŠãããŸãããã ãããžã§ã¯ãã«ããŒã¿ãã€ã³ãã£ã³ã°ã©ã€ãã©ãªãè¿œå ããŸãããã
// at the top of file apply plugin: 'kotlin-kapt' android { //other things that we already used dataBinding.enabled = true } dependencies { //other dependencies that we used kapt "com.android.databinding:compiler:3.0.0-beta1" }
ããŒã¿ãã€ã³ãã£ã³ã°ã³ã³ãã€ã©ã®ããŒãžã§ã³ã¯ããããžã§ã¯ãã®build.gradleãã¡ã€ã«ã®gradleã®ããŒãžã§ã³ãšäžèŽããå¿ èŠãããããšã«æ³šæããŠãã ããã
classpath 'com.android.tools.build:gradle:3.0.0-beta1'
[ ä»ããåæ]ãã¯ãªãã¯ããŸã ã activity_main.xmlã«ç§»åãã ConstraintLayoutãã¬ã€ã¢ãŠãã¿ã°ã§ã©ããããŸã ã
<?xml version="1.0" encoding="utf-8"?> <layout 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.support.constraint.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context="me.fleka.modernandroidapp.MainActivity"> <TextView android:id="@+id/repository_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="16dp" android:layout_marginStart="16dp" android:textSize="20sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.083" tools:text="Modern Android app" /> <TextView android:id="@+id/repository_has_issues" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="16dp" android:layout_marginStart="16dp" android:layout_marginTop="8dp" android:text="@string/has_issues" android:textStyle="bold" app:layout_constraintBottom_toBottomOf="@+id/repository_name" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="1.0" app:layout_constraintStart_toEndOf="@+id/repository_name" app:layout_constraintTop_toTopOf="@+id/repository_name" app:layout_constraintVertical_bias="1.0" /> <TextView android:id="@+id/repository_owner" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginEnd="16dp" android:layout_marginStart="16dp" android:layout_marginTop="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/repository_name" app:layout_constraintVertical_bias="0.0" tools:text="Mladen Rakonjac" /> <TextView android:id="@+id/number_of_starts" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginEnd="16dp" android:layout_marginStart="16dp" android:layout_marginTop="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="1" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/repository_owner" app:layout_constraintVertical_bias="0.0" tools:text="0 stars" /> </android.support.constraint.ConstraintLayout> </layout>
ãã¹ãŠã®xmlnsãã¬ã€ã¢ãŠãã¿ã°ã«ç§»åããå¿ èŠãããããšã«æ³šæããŠãã ããã 次ã«ã ãã«ãã¢ã€ã³ã³ãã¯ãªãã¯ããããããŒããŒãã·ã§ãŒãã«ããCtrl + F9 ïŒMacã§ã¯Cmd + F9 ïŒã䜿çšããŸãã ããŒã¿ãã€ã³ãã£ã³ã°ã©ã€ãã©ãªãActivityMainBindingã¯ã©ã¹ãçæã§ããããã«ãããžã§ã¯ãããã«ãããå¿ èŠããããŸããããã¯MainActivityã¯ã©ã¹ã§äœ¿çšããŸãã
ãããžã§ã¯ãããã«ãããªãå Žåã¯ãã³ã³ãã€ã«æã«çæãããããã ActivityMainBindingã¯ã©ã¹ã¯è¡šç€ºãããŸããã ãã€ã³ãã¯ãŸã å®äºããŠããŸãããActivityMainBindingåã®ãŒã以å€ã®å€æ°ãããããšãäŒããŸããã ããã«ãããªããèŠãããšãã§ããããã«ãç§ã¯ç€ºããŸããã§ãããïŒ ã¿ã€ãActivityMainBindingã®æåŸã«ãç§ã¯ãããåæåããŸããã§ããã ããã¯ã©ã®ããã«å¯èœã§ããïŒ lateinit修食åã䜿çšãããšããŒã以å€ã®å€æ°ãåæååŸ ã¡ã«ããããšãã§ããŸãã ButterKnifeãšåæ§ã«ã ã¢ã¯ãã£ããã£ã®æºåãã§ãããã onCreateã¡ãœããã§ãã€ã³ãã£ã³ã°ã®åæåãè¡ãå¿ èŠããããŸãã ãŸããããããonCreateã¡ãœããã®ã¹ã³ãŒãå€ã§äœ¿çšããŠããããã onCreateã¡ãœããã§ãã€ã³ãã£ã³ã°ã宣èšããªãã§ãã ããã ãã€ã³ãã£ã³ã°ã¯nullã§ãã£ãŠã¯ãªããªãã®ã§ã lateinitã䜿çšããŸã ã lateinit修食åã䜿çšãããšãã¢ã¯ã»ã¹ãããã³ã«å€æ°ãã€ã³ãã£ã³ã°ããã§ãã¯ããå¿ èŠããããŸããã
ãã€ã³ãã£ã³ã°å€æ°ãåæåããŸãããã 亀æããå¿ èŠããããŸãïŒ
setContentView(R.layout.activity_main)
ã«ïŒ
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
以äžã§ãïŒ ãã¥ãŒãæ£åžžã«ãªã³ã¯ãããŸããã ããã§ããããã«ã¢ã¯ã»ã¹ããŠå€æŽãé©çšã§ããŸãã ããšãã°ããªããžããªåããModern Android Habrahabr Articleãã«å€æŽããŸãããã
binding.repositoryName.text = "Modern Android Habrahabr Article"
ã芧ã®ããã«ã ãã€ã³ãã£ã³ã°å€æ°ãä»ããŠactivity_main.xmlããïŒãã¡ããidãæã€ïŒãã¹ãŠã®ãã¥ãŒã«ã¢ã¯ã»ã¹ã§ããŸãã ãããã ããŒã¿ãã€ã³ãã£ã³ã°ã ButterKnifeãããåªããŠããçç±ã§ã ã
ã³ããªã³ã®ã²ãã¿ãŒãšã»ãã¿ãŒ
Javaã®ããã«.setTextïŒïŒã¡ãœããããªãããšã«ãã§ã«æ°ä»ããŠãããããããŸããã ããã§ç«ã¡æ¢ãŸã£ãŠãJavaãšæ¯èŒããŠKotlinã§ã²ãã¿ãŒãšã»ãã¿ãŒãã©ã®ããã«æ©èœãããã説æããŸãã
ãŸããã»ãã¿ãŒãšã²ãã¿ãŒã䜿çšããçç±ãç¥ã£ãŠããå¿ èŠããããŸãã ãããã䜿çšããŠã¯ã©ã¹å€æ°ãé衚瀺ã«ããã¡ãœããã®ã¿ã䜿çšããŠã¢ã¯ã»ã¹ãèš±å¯ããŸããããã«ãããã¯ã©ã¹ã¯ã©ã€ã¢ã³ãããã¯ã©ã¹èŠçŽ ãé衚瀺ã«ããåãã¯ã©ã€ã¢ã³ããçŽæ¥ã¯ã©ã¹ãå€æŽããã®ãé²ããŸãã Javaã«Squareã¯ã©ã¹ããããšããŸãïŒ
public class Square { private int a; Square(){ a = 1; } public void setA(int a){ this.a = Math.abs(a); } public int getA(){ return this.a; } }
setAïŒïŒã¡ãœããã䜿çšããŠãæ£æ¹åœ¢ã®åŽã«è² ã®å€ãèšå®ããããšãã¯ã©ã¹ã¯ã©ã€ã¢ã³ãã«çŠæ¢ããŸã;ããã¯è² ã§ãã£ãŠã¯ãªããŸããã ãã®ã¢ãããŒãã䜿çšããŠããã©ã€ããŒããäœæããå¿ èŠããããããçŽæ¥ã€ã³ã¹ããŒã«ã§ããŸããã ãŸããã¯ã©ã¹ã®ã¯ã©ã€ã¢ã³ããçŽæ¥ååŸã§ããªããããã²ãã¿ãŒãæäŸããå¿ èŠããããŸãã ãã®ã²ãã¿ãŒã¯ãè¿ããŸãã åæ§ã®èŠä»¶ãæã€10åã®å€æ°ãããå Žåã10åã®ã²ãã¿ãŒãæäŸããå¿ èŠããããŸãã ãã®ãããªè¡ãæžãããšã¯éå±ãªããšã§ãããéåžžãç§ãã¡ã¯å¿ã䜿ããŸããã
Kotlinã¯éçºè ã®ç掻ã楜ã«ããŸãã ããªããé»è©±ããå Žå
var side: Int = square.a
ããã¯ãã«çŽæ¥ã¢ã¯ã»ã¹ããŠãããšããæå³ã§ã¯ãããŸããã ããã¯ãšåãã§ã
int side = square.getA();
Javaã§ã ãã®çç±ã¯ãKotlinãããã©ã«ãã®ã²ãã¿ãŒãšã»ãã¿ãŒãèªåçã«çæããããã§ãã Kotlinã§ã¯ãç¹å¥ãªã»ãã¿ãŒãŸãã¯ã²ãã¿ãŒãããå Žåã«ã®ã¿æå®ããå¿ èŠããããŸãã ãã以å€ã®å ŽåãKotlinã¯èªåçã«çæããŸãïŒ
var a = 1 set(value) { field = Math.abs(value) }
ãã£ãŒã«ã ïŒ ããã¯äœã§ãã æ確ã«ããããã«ããã®ã³ãŒããèŠãŠã¿ãŸãããã
var a = 1 set(value) { a = Math.abs(value) }
ããã¯ãKotlinã¯ãŒã«ãã§ã¯ããããã£ã«çŽæ¥ã¢ã¯ã»ã¹ã§ããªãããã setã¡ãœããå ã§setã¡ãœãããåŒã³åºããŠããããšãæå³ããŸãã ããã«ãããç¡éã®ååž°ãäœæãããŸãã a = somethingãåŒã³åºããšãèªåçã«setã¡ãœãããåŒã³åºãããŸãã
ãã£ãŒã«ãããŒã¯ãŒãã䜿çšããçç±ãšãã»ãã¿ãŒãšã²ãã¿ãŒã®åäœæ¹æ³ãæããã«ãªã£ãããšãé¡ã£ãŠããŸãã
ã³ãŒãã«æ»ããŸãããã Kotlinèšèªã®ãã1ã€ã®åªããæ©èœã玹ä»ããããšæããŸã ã
class MainActivity : AppCompatActivity() { lateinit var binding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = DataBindingUtil.setContentView(this, R.layout.activity_main) binding.apply { repositoryName.text = "Medium Android Repository Article" repositoryOwner.text = "Fleka" numberOfStarts.text = "1000 stars" } } }
applyã䜿çšãããšãåäžã€ã³ã¹ã¿ã³ã¹ã§è€æ°ã®ã¡ãœãããåŒã³åºãããšãã§ããŸãã
ããŒã¿ãã€ã³ãã£ã³ã°ã¯ãŸã å®äºããŠããŸãããããŸã ããããšããããããããŸãã ãªããžããªã®ãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ã¢ãã«ã¯ã©ã¹ãäœæããŸãããïŒGitHubãªããžããªã®ãã®ãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ã¢ãã«ã¯ã©ã¹ã¯ã衚瀺ããããŒã¿ãæ ŒçŽããŸãã ãªããžããªãã¿ãŒã³ãšæ··åããªãã§ãã ããïŒã Kotlinã¯ã©ã¹ãäœæããã«ã¯ãNew- > Kotlin File / Classã«ç§»åããå¿ èŠããããŸãã
class Repository(var repositoryName: String?,var repositoryOwner: String?,var numberOfStars: Int? ,var hasIssues: Boolean = false)
Kotlinã§ã¯ããã©ã€ããªã³ã³ã¹ãã©ã¯ã¿ãŒã¯ã¯ã©ã¹ããããŒã®äžéšã§ãã 2çªç®ã®ã³ã³ã¹ãã©ã¯ã¿ãæäŸããããªãå Žåã¯ãããã ãã§ãïŒ ã¯ã©ã¹ã®äœæã«é¢ããäœæ¥ã¯ããã§å®äºããŸããã ãã£ãŒã«ãå²ãåœãŠçšã®ã³ã³ã¹ãã©ã¯ã¿ãŒãã©ã¡ãŒã¿ãŒãã²ãã¿ãŒããã³ã»ãã¿ãŒã¯ãããŸããã ã¯ã©ã¹å šäœã1è¡ã§ïŒ
MainActivity.ktã¯ã©ã¹ã«æ»ãã ãªããžããªã¯ã©ã¹ãã€ã³ã¹ã¿ã³ã¹åããŸã ã
var repository = Repository("Habrahabr Android Repository Article", "Fleka", 1000, true)
ã芧ã®ãšããããªããžã§ã¯ããäœæããããã«æ°ããããŒã¯ãŒãã¯å¿ èŠãããŸããã
次ã«ã activity_main.xmlã«ç§»åããŠã ããŒã¿ã¿ã°ãè¿œå ããŸãããã
<data> <variable name="repository" type="me.fleka.modernandroidapp.uimodels.Repository" /> </data>
ã¬ã€ã¢ãŠãå ã®ãªããžããªã¿ã€ãã§ãããªããžããªå€æ°ã«ã¢ã¯ã»ã¹ã§ããŸãã ããšãã°ãèå¥årepository_nameã䜿çšããŠTextViewã§æ¬¡ã®æäœãå®è¡ã§ããŸã ã
android:text="@{repository.repositoryName}"
TextView repository_nameã«ã¯ã ãªããžããªå€æ°ã®repositoryNameããããã£ããååŸããããã¹ãã衚瀺ãããŸãã xmlã®ãªããžããªå€æ°ãMainActivity.ktã®ãªããžããªã«ãã€ã³ãããããšã®ã¿ãæ®ããŸã ã
[ ãã«ã]ãã¯ãªãã¯ããŠããŒã¿ãã€ã³ãã£ã³ã°ã©ã€ãã©ãªãçæããå¿ èŠãªã¯ã©ã¹ãäœæãã MainActivityã«æ»ã£ãŠ2è¡è¿œå ããŸãã
binding.repository = repository binding.executePendingBindings()
ã¢ããªã±ãŒã·ã§ã³ãå®è¡ãããšã TextViewã« ãHabrahabr Android Repository Articleãã衚瀺ãããŸãã è¯ãæ©èœã§ãã :)
ãããã以äžãå®è¡ãããšã©ããªããŸããïŒ
Handler().postDelayed({repository.repositoryName="New Name"}, 2000)
æ°ããããã¹ãã¯2ç§åŸã«è¡šç€ºãããŸããïŒ ãããã衚瀺ãããŸããã ãªããžããªå€ããªã»ããããå¿ èŠããããŸãã ãã®ãããªäœããåäœããŸãïŒ
Handler().postDelayed({repository.repositoryName="New Name" binding.repository = repository binding.executePendingBindings()}, 2000)
ãã ããããããã£ãå€æŽãããã³ã«ãããè¡ãå¿ èŠãããå Žåã¯éå±ã§ãã Property Observerãšããåªãããœãªã¥ãŒã·ã§ã³ããããŸãã
ãŸãã Observerãã¿ãŒã³ãšã¯äœãã説æããŸããããrxJavaã»ã¯ã·ã§ã³ã§ãããå¿ èŠã«ãªããŸãã
ãã§ã«androidweekly.netã«ã€ããŠèããããšããããããããŸããã ããã¯ãæ¯é±ã®Androidéçºãã¥ãŒã¹ã¬ã¿ãŒã§ãã åãåãããå Žåã¯ãã¡ãŒã«ã¢ãã¬ã¹ãå ¥åããŠè³Œèªããå¿ èŠããããŸãã åŸã§ãå¿ èŠã«å¿ããŠããµã€ãããã®ç»é²è§£é€ãåæ¢ã§ããŸãã
ããã¯ã Observer / Observableãã¿ãŒã³ã®äžäŸã§ãã ãã®å ŽåãAndroid Weeklyã¯Observableã§ãããæ¯é±ãã¥ãŒã¹ã¬ã¿ãŒããªãªãŒã¹ããŸãã èªè ã¯ãªãã¶ãŒããŒã§ãã ã圌ãã¯ããã賌èªããæ°ãããªãªãŒã¹ãåŸ ã¡ããããåãåã£ããããã«ãããèªã¿ã圌ãã®äœäººãããããæ°ã«å ¥ããªããšå€æãããã圌/圌女ã¯èŠãã®ããããããšãã§ãã
ãã®å Žåã ããããã£ãªãã¶ãŒããŒã¯ã ãªããžããªã€ã³ã¹ã¿ã³ã¹ã®å€æŽããªãã¹ã³ããXMLã¬ã€ã¢ãŠãã§ãã ãããã£ãŠã ãªããžããªã¯ç£èŠå¯èœã§ãã ããšãã°ã Repositoryã¯ã©ã¹ã®nameããããã£ãã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹ã§å€æŽããããšããã«ãxmlãåŒã³åºããŠæŽæ°ããå¿ èŠããããŸãã
binding.repository = repository binding.executePendingBindings()
ããŒã¿ãã€ã³ãã£ã³ã°ã©ã€ãã©ãªã䜿çšããŠãããè¡ãæ¹æ³ã¯ïŒ ããŒã¿ãã€ã³ãã£ã³ã°ã©ã€ãã©ãªã¯ã BaseObservableã¯ã©ã¹ãæäŸããŸããããã¯ã Repositoryã¯ã©ã¹ã«å®è£ ããå¿ èŠããããŸã ã
class Repository(repositoryName : String, var repositoryOwner: String?, var numberOfStars: Int? , var hasIssues: Boolean = false) : BaseObservable(){ @get:Bindable var repositoryName : String = "" set(value) { field = value notifyPropertyChanged(BR.repositoryName) } }
BRã¯ã Bindableã¢ãããŒã·ã§ã³ã䜿çšããããšãã«1åèªåçã«çæãããã¯ã©ã¹ã§ãã ã芧ã®ãšãããæ°ããå€ãèšå®ããããšããã«ãããã«ã€ããŠåŠç¿ããŸãã ããã§ãã¢ããªã±ãŒã·ã§ã³ãèµ·åã§ãã2ç§åŸã«executePendingBindingsïŒïŒé¢æ°ãå床åŒã³åºããã«ãªããžããªåãå€æŽãããããšãããããŸãã
ãã®éšåã¯ä»¥äžã§ãã 次ã®ããŒãã§ã¯ã MVVMãã¿ãŒã³ã ãªããžããªãã¿ãŒã³ã Androidã©ãããŒãããŒãžã£ãŒã«ã€ããŠèª¬æããŸãã ããã§ãã¹ãŠã®ã³ãŒããèŠã€ããããšãã§ããŸãã ãã®èšäºã§ã¯ã ãã®ã³ãããã®åã®ã³ãŒãã«ã€ããŠèª¬æããŸãã