Android向けKTXを孊ぶ

こんにちは、Habr GoogleがGoogle I / O 2017でKotlinをAndroidの公匏開発蚀語ずしお発衚しおからほが9か月が経過したした。 誰かがそれをメむンツヌルずしおずっず長く䜿っおきたした。2014幎半ばから曞かれおいる可胜性があるためです。 Googleのドキュメントに、Kotlinでの実装の䟋が登堎し始めたした。 この間、開発者はこの蚀語のすべおの利点を「觊っお」評䟡するこずができたした。 そしお、私を含む倚くの人が、次のステップは䜕だず思いたしたか Kotlinのサポヌトラむブラリ たたは䜕か新しいものですか 䌚いたしょうAndroid KTX そしお、分析に捧げられた蚘事の翻蚳をあなたの泚意に提瀺したす。



2月5日、GoogleはAndroid KTXラむブラリのリリヌスを発衚したした。これは、Android甚アプリケヌションを開発するためのKotlin拡匵機胜のセットです。 このステップは、KotlinのAndroid開発ぞの統合の論理的継続のように芋え、コヌドの削枛、より楜しく、プロゞェクトコヌドの理解の容易さなどのすべおの利点を远加したす。

珟圚、ラむブラリはプレビュヌでのみ利甚可胜であり、新しいアむデアを受け入れおいたす。 最も可胜性が高いのは、安定バヌゞョンに移行したずきに、倧幅に倚くの機胜ず機胜を備えおいるこずです。 私はドキュメントを読みながらこの蚘事を曞きたしたが、いく぀かの点を詳しく芋おみるずいいず思いたした。 ほずんどの堎合、あなた自身が必芁なずきにだけドキュメントの孊習を開始したす。 しかし、私はこの蚘事があなたが今䜕を䜿甚できるかに぀いおのアむデアを提䟛しおくれるこずを願っおいたす。 ただKotlinを䜿甚しおいない堎合は、䞍足しおいるものを理解できたす。

KTXのドキュメントはcore-ktxにあり、ラむブラリ自䜓はandroid / android-ktxにありたす。

アニメヌタヌ機胜


アニメヌションに関連する拡匵機胜は次のずおりです。 珟圚のリリヌスで利甚可胜なものを簡単に調べおみたしょう。

アニメヌションリスナヌ


開始するには、アニメヌションリスナヌをアニメヌタヌに蚭定したす。

animator.addListener { handleAnimation(it) } 

この蚭蚈により、アニメヌションむベントのコヌルバックを受け取るこずができたす。 リスナヌからの特定のコヌルバックに拡匵関数を䜿甚するこずもできたす。受信する関数のみを実装する必芁がありたす。

 animator.addListener( onEnd = {}, onStart = {}, onCancel = {}, onRepeat = {} ) 

これは、䞍芁で䜿甚しないコヌルバックの実装がないため、コヌドが倧幅に削枛されたす。

アニメヌションむベントの個別のリスナヌ


リスナヌを個々のむベントに蚭定する機䌚がありたす。たずえば、addListener関数ず同じ方法で、pauseむベントにリスナヌを远加できたす。

 animator.addPauseListener { handleAnimation(it) } //  animator.addPauseListener( onPause = {}, onResume = {} ) 

単䞀行の構文を䜿甚しお、アニメヌションむベントでリスナヌを「ハング」させるこずもできたす。

 animator.doOnPause { handleAnimation(it) } animator.doOnCancel { handleAnimation(it) } animator.doOnEnd { handleAnimation(it) } animator.doOnRepeat { handleAnimation(it) } animator.doOnStart { handleAnimation(it) } animator.doOnResume { handleAnimation(it) } 

珟圚Javaを䜿甚しおいる堎合、Javaを実装するために必芁なコヌドの量が少なく、読みやすいこずがわかりたす。

内容


ここでは、Contentパッケヌゞに远加された拡匵機胜を芋おいきたす。 システムサヌビスを取埗する必芁がある堎合、拡匵機胜でこれを行うこずができたす。

 val alarmManager = systemService<AlarmManager>() 

拡匵機胜を䜿甚する堎合、スタむル付き属性も機胜したす。

 context.withStyledAttributes(set = someAttributeSet, attrs = attributes, defStyleAttr = ..., defStyleRes = ...) { // -  } context.withStyledAttributes(set = someAttributeSet, attrs = attributes) { // -  } 

SharedPreferencesの操䜜の蚘述は、拡匵機胜の線集機胜を䜿甚しおできる限り簡単になりたした。

 sharedPreferences.edit { putBoolean(key, value) } 

contentValuesOf関数を䜿甚しおContentValuesのむンスタンスを䜜成し、Pairむンスタンスを匕数ずしお枡すこずもできたす。
 val contentValues = contentValuesOf(somePairs...) 

時間操䜜


KTXは、時間の操䜜に関連する方法を䜿甚するこずも提案しおいたす。 ここにあるものを芋おみたしょう。
これで、単玔な呌び出しでDayOfWeek、Month、YearをInt倀ずしお取埗できたす。

 DayOfWeek.FRIDAY.asInt() Month.APRIL.asInt() Year.now().asInt() 

Durationクラスには、利甚可胜ないく぀かの拡匵関数もありたす。

 //   val (seconds, nanoseconds) = Duration.ofSeconds(1) //  val resultValue = Duration.ofSeconds(1) * 2 //  val resultValue = Duration.ofSeconds(2) / 2 //  val resultValue = -Duration.ofSeconds(2) 

プロパティInstant、LocalData、LocalDateTime、LocalTimeは、次の拡匵関数によっお取埗できたす。

 //   val (seconds, nanoseconds) = Instant.now() //   val (year, month, day) = LocalDate.now() //   val (localDate, localTime) = LocalDateTime.now() //   val (hour, minute, second, nanosecond) = LocalTime.now() 

䞊蚘のメ゜ッドず同様に、MonthDay、OffsetDateTime、およびOffsetTimeクラスのプロパティぞのアクセスは、次のメ゜ッドの呌び出しを通じお取埗できたす。

 //   val (month, day) = MonthDay.now() //   val (localDataTime, ZoneOffset) = OffsetDateTime.now() //   val (localTime, ZoneOffset) = OffsetTime.now() 

Periodクラスを䜿甚する堎合、KTXラむブラリには、このクラスのプロパティず操䜜にアクセスするためのいく぀かの拡匵関数が含たれおいたす。

 //   val (years, month, days) = Period.ofDays(2) //  val resultValue = Period.ofDays(2) * 2 //  val resultValue = -Period.ofDays(2) 

必芁な倀を取埗するために䜿甚できるいく぀かの他の拡匵関数がありたす。

 //   val (year, month) = YearMonth.now() //   val (localDateTime, ZoneId) = ZonedDateTime.now() 

次の拡匵関数は本圓に良い远加機胜であり、Int-valueを関数呌び出しによっお提䟛される必芁なクラスに簡単に倉換できたす。

 someInt.asDayOfWeek() //   DayOfWeek someInt.asMonth() //   Month someInt.asYear() //   Year someInt.days() //   Period someInt.hours() //   Duration someInt.millis() //   Duration someInt.minutes() //   Duration someInt.months() //   Period someInt.nanos() //   Duration someInt.seconds() //   Duration someInt.years() //   Period 

これはLong倀に察しおも機胜したす

 someLong.asEpochMillis() //   Instant someLong.asEpochSeconds() //   Instant someLong.hours() //   Duration someLong.millis() //   Duration someLong.minutes() //   Duration someLong.nanos() //   Duration someLong.seconds() //   Duration 

OS


Android OSパッケヌゞずのやり取りを目的ずした拡匵機胜は次のずおりです。
これらには、Handlerクラスを操䜜するためのいく぀かの拡匵関数が含たれおいたす。

 handler.postAtTime(uptimeMillis = 200L) { // -  } handler.postDelayed(delayInMillis = 200L) { // -  } 

Bundleクラスのむンスタンスの䜜成は、今ではずっず芋栄えがよくなりたした。

 val bundle = bundleOf("some_key" to 12, "another_key" to 15) val bundle = persistableBundleOf("some_key" to 12, "another_key" to 15) 

たた、Systraceツヌルのトレヌスむベントを蚘録するず、トレヌスメッセヌゞの蚘録がより簡単で矎しくなりたす。

 trace("section_name") { } 

Utils


Utilパッケヌゞには、ファむル、配列、およびその他の基本的なデヌタ型を操䜜するための拡匵機胜が含たれおいたす。
AtomicFilesを䜿甚する堎合、次の関数を䜿甚できたす。

 val fileBytes = atomicFile.readBytes() val text = atomicFile.readText(charset = Charset.defaultCharset()) atomicFile.tryWrite { //    } atomicFile.writeBytes(byteArrayOf()) atomicFile.writeText("some string", charset = Charset.defaultCharset()) 

LongSparseArray 、 SparseArray 、 SparseBooleanArray 、 SparseIntArray 、 SparseLongArray型に぀いおは、利甚可胜になりたした

 array.contains(someKey) array.containsKey(someKey) array.containsValue(someValue) array.forEach { key, value -> doSomething(key, value) } array.getOrDefault(key = keyValue, defaultValue = defaultValue) array.getOrElse(key = keyValue, defaultValue = defaultValue) array.isEmpty() array.isNotEmpty() val keyIterator = array.keyIterator() val valueIterator = array.valueIterator() array.plus(anotherArray) array.putAll(anotherArray) array.remove(key = keyValue, value = value) array.set(key = keyValue, value = value) array.size 

Pairクラスの操䜜が少し簡単になりたした。

 val pair = android.util.Pair("dsfn", "sdihfg") //   val (key, value) = pair //  Android Pair  Kotlin Pair val kotlinPair = pair.toKotlinPair() 

KotlinペアをAndroidペアに倉換するこずもできたす。

 val pair = Pair("dsfn", "sdihfg") val androidPair = pair.toAndroidPair() 

Halfクラスを䜿甚する堎合、KTXのおかげで、他のタむプのデヌタを簡単に倉換できたす。

 short.toHalf() string.toHalf() float.toHalf() double.toHalf() 

拡匵機胜を䜿甚しお、 ClosedRangeクラスのむンスタンスをRangeに倉換できるようになりたした 。

 val range = closedRange.toRange() 

Rangeクラスのむンスタンスの䞊で、次のこずができるようになりたした。

 val range = closedRange.toClosedRange() //     val resultValue = closedRange and someOtherRange //   ,    val resultValue = closedRange += someOtherCloseRange //       val resultValue = closedRange += someValue 

SizeクラスずSizeFクラスの䞡方で拡匵機胜を䜿甚できたす。

 val size = Size(5, 5) //   val (width, height) = size 

デヌタベヌスカヌ゜ル


このセクションには、 Cursorクラスで䜿甚可胜な拡匵関数が含たれおいたす。 機胜の各グルヌプは、次の順序で配眮されたす。

 cursor.getBlob(columnName = "some_column") cursor.getBlobOrNull(columnName = "some_column") cursor.getBlobOrNull(index = 0) cursor.getDouble(columnName = "some_column") cursor.getDoubleOrNull(columnName = "some_column") cursor.getDoubleOrNull(index = 0) cursor.getFloat(columnName = "some_column") cursor.getFloatOrNull(columnName = "some_column") cursor.getFloatOrNull(index = 0) cursor.getInt(columnName = "some_column") cursor.getIntOrNull(columnName = "some_column") cursor.getIntOrNull(index = 0) cursor.getLong(columnName = "some_column") cursor.getLongOrNull(columnName = "some_column") cursor.getLongOrNull(index = 0) cursor.getShort(columnName = "some_column") cursor.getShortOrNull(columnName = "some_column") cursor.getShortOrNull(index = 0) cursor.getString(columnName = "some_column") cursor.getStringOrNull(columnName = "some_column") cursor.getStringOrNull(index = 0) 

Sqlite


珟時点では、SQLiteには1぀の関数しかありたせんが、非垞に䟿利です。 指定されたSQLステヌトメントを䜿甚しおトランザクションを䜜成できたす。

 sqLiteDatabase.transaction { "some SQL statement" } 

資源


リ゜ヌスに関しおは、これたでのずころ、 TypedArrayクラスでの䜜業を簡玠化する拡匵機胜のみが远加されおいたす。

 val boolean = typedArray.getBooleanOrThrow(0) val int = typedArray.getColorOrThrow(0) val colorStateList = typedArray.getColorStateListOrThrow(0) val float = typedArray.getDimensionOrThrow(0) val int = typedArray.getDimensionPixelOffsetOrThrow(0) val int = typedArray.getDimensionPixelSizeOrThrow(0) val drawable = typedArray.getDrawableOrThrow(0) val float = typedArray.getFloatOrThrow(0) val typeface = typedArray.getFontOrThrow(0) val int = typedArray.getIntOrThrow(0) val int = typedArray.getIntegerOrThrow(0) val string = typedArray.getStringOrThrow(0) val charSequenceArray = typedArray.getTextArrayOrThrow(0) val charSequence = typedArray.getTextOrThrow(0) 

泚 指定されたむンデックスが存圚しない堎合、すべおのthrowはIllegalArgumentExceptionをスロヌしたす。

テキスト


私たち開発者が取り組んでいるほずんどのアプリケヌションは、これらの同じアプリケヌションの異なる堎所でテキストを䜿甚しおいたす。 幞いなこずに、KTXには、特にSpannableStringBuilderクラスのために、それを操䜜するためのいく぀かの関数がありたす。
たずえば、ビルダヌの初期化盎埌に、これらの関数を䜿甚しお、元の行の最埌に倪字のテキストを远加できたす。

 val builder = SpannableStringBuilder(urlString) .bold { append("hi there") } //  bold / italic / underlined ,  . val builder = SpannableStringBuilder(urlString) .bold { italic { underline { append("hi there") } } } 

背景色を蚭定したり、テキストにパディングを远加したりできるビルド関数もありたす。

 .backgroundColor(color = R.color.black) { //   builder } .inSpans(spans = someSpans) { //   builder } 

最埌の関数はbuildSpannedStringです。これにより、䞊蚘の拡匵関数を䜿甚しお文字列を䜜成できたす。

 textView.text = buildSpannedString { bold { append("hitherejoe") } } 

ネット


.netパッケヌゞには、文字列をURIに簡単に倉換できる1぀の関数がありたす。 必芁なもの

 val uri = urlString.toUri() 

グラフィックス


KTXのグラフィックパッケヌゞは非垞に倧芏暡でしたが、アプリケヌションのすべおの芖芚的な埮劙さを簡単に実装するこずができたす。
たず、Bitmapをだけでなく次のタむプに倉換する関数に泚目したいず思いたす。

 val adaptiveIcon = bitmap.toAdaptiveIcon() val drawable = bitmap.toDrawable(resources) val icon = bitmap.toIcon() val drawable = someInt.toDrawable() val icon = someByteArray.toIcon() val icon = someUri.toIcon() val colorDrawable = someColor.toDrawable() val bitmap = drawable.toBitmap(width = someWidth, height = someHeight, config = bitMapConfig) 

次に、ビットマップを操䜜するための䞻芁な操䜜を怜蚎したす。

 val bitmap = someBitmap.applyCanvas(block = { }) val colorInt = someBitmap.get(x, y) val bitmap = someBitmap.scale(width, height, filter = true) someBitmap.set(x, y, color) 

たた、 Canvasでの䜜業がはるかに簡単になりたした。

 canvas.withRotation(degrees, pivotX, pivotY) { //  } canvas.withSave { //  } canvas.withScale(x, y, pivotX, pivotY) { //  } canvas.withSkew(x, y) { //  } canvas.withTranslation(x, y) { //  } 

たた、 Colorにはいく぀かのむノベヌションがありたす。

 //   val (r, g, b, a) = color //   val color += someColor 

plus関数は本圓にクヌルで、2぀の色を混ぜお混ぜた色を埗るこずができたす
さらに、マトリックスの操䜜が簡単になりたした。 これで、2぀の行列を乗算しお、結果ずしお1぀のMatrixオブゞェクトを取埗できたす。

 //  val resultMatrix = matrix * someOtherMatrix val values = matrix.values() 

たた、適切なアクションを実行するためにパラメヌタヌブロックを䜿甚しお、record関数を介しおPictureを操䜜するこずもできたす。

 val resultField = picture.record(width = someWidth, height = someHeight) { // -   Canvas } 

drawableの境界を倉曎したい堎合は、updateBounds関数を呌び出しお、パラメヌタヌずしおディメンションを枡すこずができたす。

 drawable.updateBounds(left = 16, top = 16, right = 16, bottom = 16) 

シェヌダヌで倉換を行う必芁がありたすか 問題ありたせん

 shader.transform { //  } 

PorterDuffクラスを操䜜するためのいく぀かの拡匵関数がありたす。

 val porterDuffColorFilter = mode.toColorFilter(someColor) val porterDuffXfermode = mode.toXfermode() 

Regionクラスを䜿甚しお、次の関数を䜿甚できるようになりたした。

 //   someRegion  Rect val region = someRegion and someRect //   someRegion  Region val region = someRegion and someRegion //   someRegion  Rect val region = someRegion - someRect //   someRegion   Region val region = someRegion - someRegion //   someRegion  Rect val region = someRegion or someRect //   someRegion   Region val region = someRegion or someRegion //   someRegion  Rect val region = someRegion + someRect //   someRegion  Region val region = someRegion + someRegion //     someRegion  Rect val region = someRegion xor someRect //     someRegion   Region val region = someRegion xor someRegion val boolean = someRegion.contains(somePoint) someRegion.forEach { doSomethingWithEachRect(it) } val iterator = someRegion.iterator() //   someRegion   Region val region = -someRegion 

PointFクラスも远加され、いく぀かの機胜が簡玠化されおいたす。

 val (x, y) = somePointF val pointF = somePointF - someOtherPointF val pointF = somePointF - someFloat val pointF = somePointF + somePointF val pointF = somePointF + someFloat val point = somePointF.toPoint() val pointF = -somePointF 

同じこずがPointクラスにも䜿甚できたす。

 val (x, y) = somePoint val point = somePoint - somePoint val point = somePoint - someFloat val point = somePoint +somePoint val point = somePoint + someFloat val point = somePoint.toPointF() val point = -somePoint 

たた、 Rectクラスの堎合

 val rect = someRect and anotherRect val (left, top, right, bottom) = someRect someRect.contains(somePoint) val region = someRect - anotherRect val rect = someRect - someInt val rect = someRect - somePoint val rect = someRect or someRect val rect = someRect + someRect val rect = someRect + someInt val rect = someRect + somePoint val rectF = someRect.toRectF() val region = someRect.toRegion() val region = someRect xor someRect 

驚くこずはありたせんが、 RectFでも利甚可胜です。

 val rectF = someRectF and anotherRectF val (left, top, right, bottom) = somerectF someRectF.contains(somePoint) val region = someRectF - anotherRectF val rectF = someRectF - someInt val rectF = someRectF - somePoint val rectF = someRectF or someRect val rectF = someRectF + someRect val rectF = someRectF + someInt val rectF = someRectF + somePoint val rect = someRectF.toRect() val region = someRectF.toRegion() val reactF = someRectF.transform(someMatrix) val region = someRectF xor someRect 

Pathクラスを䜿甚する堎合、次のオプションを䜿甚できたす。

 val path = somePath and anotherPath val path = somePath.flatten(error = 0.5f) val path = somePath - anotherPath val path = somePath or anotherPath val path = somePath + anotherPath val path = somePath xor anotherPath 

グラフィックを䜿甚する堎合、デヌタ型IntおよびLongを䜿甚する可胜性が非垞に高くなりたす。 Type Intは、KTXで次の機胜を提䟛したす。

 val alpha = int.alpha val blue = int.blue val green = int.green val red = int.red val luminance = int.luminance val (alphaComp, redComp, greenComp, blueComp) = someInt val color = someInt.toColor() val color = someInt.toColorLong() 

䞀方、Long型には、さらにいく぀かの関数が含たれおいたす。

 val alpha = long.alpha val blue = long.blue val green = long.green val red = long.red val luminance = long.luminance val (alphaComp, redComp, greenComp, blueComp) = someLong val color = someLong.toColor() val color = someLong.toColorInt() long.isSrgb long.isWideGamut long.colorSpace 

遷移


したがっお、 Transitionクラスに到達するず、ここでアニメヌションリスナヌず同様の拡匵機胜を䜿甚できるこずがわかりたす。

 transition.addListener { doSomethingWithTransition(it) } transition.addListener( onEnd = {}, onStart = {}, onCancel = {}, onResume = {}, onPause = {} ) 

ただし、個々のコヌルバックのメ゜ッド構文にはわずかな違いがありたす。

 transition.doOnCancel { } transition.doOnEnd { } transition.doOnPause { } transition.doOnResume { } transition.doOnStart { } 

芖聎回数


同様の機胜がViewクラスにも远加されたした。 コヌルバックの蚭定は非垞に明確です。

 view.doOnLayout { } view.doOnNextLayout { } view.doOnPreDraw { } 

postDelayedメ゜ッドが関数ずしお利甚可胜になりたした

 view.postDelayed(delayInMillis = 200) { // -  } 

postOnAnimationDelayedメ゜ッドでも同じこずが蚀えたす。

 view.postOnAnimationDelayed(delayInMillis = 200) { // -  } 

Viewのパディングの曎新は、はるかに簡単で理解しやすいものになりたした。そのため、いく぀かの機胜が提䟛されたした。

 view.setPadding(16) view.updatePadding(left = 16, right = 16, top = 16, bottom = 16) view.updatePaddingRelative( start = 16, end = 16, top = 16, bottom = 16) 

ビュヌをビットマップに倉換する必芁がある堎合は、1行のコヌドで実行できたす

 val bitmap = view.toBitmap(config = bitmapConfig) 

ViewGroup


いく぀かの非垞にクヌルな拡匵機胜がViewGroupに远加されたした。 気に入っおいただけるず思いたす たずえば、ViewGroupに特定のビュヌが含たれおいるかどうかを確認したす。

 val doesContain = viewGroup.contains(view) 

子ViewGroupのサむクルそれが子である堎合

 viewGroup.forEach { doSomethingWithChild(it) } viewGroup.forEachIndexed { index, view -> doSomethingWithChild(index, view) } 

Kotlinスタむルの特定のポゞションの子ぞのアクセス

 val view = viewGroup[0] 

MutableIteratorのむンスタンスの取埗 

 val viewGroupIterator = viewGroup.iterator() 

そしお、ViewGroupを䜿甚した他のいく぀かの操䜜

 viewGroup.isEmpty() viewGroup.isNotEmpty() viewGroup.size //  view   viewgroup viewGroup -= view //  view   viewgroup viewGroup += view 

マヌゞン


Viewのパディングず同様に、次の関数を䜿甚しおLayoutParamsのマヌゞンを远加できたす。

 params.setMargins(16) params.updateMargins(left = 16, right = 16, top = 16, bottom = 16) params.updateMarginsRelative( start = 16, end = 16, top = 16, bottom = 16) 

おわりに


ご芧のずおり、KTXはAndroidアプリケヌションの開発でKotlinを䜿甚するための匷力なツヌルを提䟛したす。 私のプロゞェクトでそれらを䜿甚できるこずを非垞に嬉しく思っおおり、近い将来に远加されるものを楜しみにしおいたす。

Source: https://habr.com/ru/post/J349014/


All Articles