
/ Asli /
Sintaksis bahasa Kotlin adalah hal yang agak fleksibel dan keringkasan kode, yang di Jawa hanya dapat dicapai dengan bantuan pembuatan kode, di Kotlin sering diimplementasikan menggunakan alat bahasa standar ( satu , dua ).
, Kotlin ( ), MVP- Summer Kotlin Multiplatform.
MVP ?
Android, Fragment Activity . , , , view view . , . MVP- , view . , , view, .
. , Moxy APT (Annotation Processing Tool). Moxy MVP-. , .
APT?
- Moxy
@InjectViewState
Fragment- , , . Moxy .
e: <...>/kapt3/stubs/debug/adev/TestFragment.java:16: error: cannot find symbol
public TestPresenterFactory presenterFactory;
^
symbol: class TestPresenterFactory
location: class TestFragment
e: <...>/kapt3/stubs/debug/adev/ui/TestFragment.java:22:
error: [ComponentProcessor:MiscError] dagger.internal.codegen.ComponentProcessor was unable to process this class because not all of its dependencies could be resolved. Check for compilation errors or a circular dependency with generated code.
public final class TestFragment extends adev.ui.BaseFragment implements adev.presentation.TestView {
^

, , Dagger , . 4 , , . , .
Fragment . . Clean Project , , .

. — AutoFactory, , .
Dagger. , , . , . APT .
APT Kotlin/MultiplatformKotlin/Multiplatform API . Annotation Processing . API .
?
Android-only APT. Koin/Kodein Dagger, FragmentArgs. Moxy . , Google MVVM, - , , . , , .
Kotlin/JS 2017 . property- VueJS , . : " Fragment/Activity?" . :
interface View {
var counter: Int
}
class Presenter : BasePresenter<View>() {
override fun createViewProxy(view: View) = object : View {
override var counter by state(view::counter, initial = 0)
}
override fun onEnter() {
viewProxy.counter = 1
}
}
view viewProxy
, view. view property delegate, state
. view view . , , view , . Map. view createViewProxy
state
Map .
:
createViewProxy
viewProxy
. . , BottomSheet .- , view.
. "".
№1.
, viewProxy
view. , , . viewProxy
view , , state
, view c .
:
interface View {
var counter: Int
}
class Presenter : BasePresenter<View>() {
override val viewProxy = object : View {
override var counter by state({ ::counter }, initial = 0)
}
override fun onCreate() {
viewProxy.counter = 1
}
}
abstract class BasePresenter<TView> {
fun <T> state(
rule: TView.() -> KMutableProperty0<T>
): StateDelegate<T> {}
}
Kotlin : obj::prop
. :
class A {
var b = 1
val prop = ::b
}
: ", , this
receiver- !".
class A {
var b = 1
}
fun A.foo() {
val prop = ::b
}
. ! !
:
interface View {
var counter: Int?
}
class Presenter : BasePresenter<View>() {
override val viewProxy = object : View {
override var counter by state({ ::counter }, initial = null)
}
}
...
e: <...>/adev/presentation/Presenter.kt: (7, 22): Type of 'counter' doesn't match the type of the overridden var-property 'public abstract var counter: Int? defined in adev.presentation.View'

, Android Studio . . ? , frontend Kotlin, , viewProxy
, , IDE, , , this
, state
. , counter
::counter
, this::counter
, .
view : this
.
abstract class BasePresenter<TView> {
fun <T> state(
rule: (TView) -> KMutableProperty0<T>
): StateDelegate<T> {}
}
:
interface View {
var counter: Int?
}
class Presenter : BasePresenter<View>() {
override val viewProxy = object : View {
override var counter by state({ it::counter }, initial = null)
}
}
. . , view . , viewProxy
Intellij IDEA/Android Studio.
: ?
:
. . .object View {
interface State {
var counter: Int
}
interface Methods {
fun showMessage(message: String)
}
}
class Presenter : BasePresenter<View.State, View.Methods>() {
override val viewStateProxy = object : View.State {
override var counter by state({ it::counter }, initial = 0)
}
override fun onEnter() {
viewStateProxy.counter = 1
viewMethods?.showMessage("Hello!")
}
}
, viewMethods
. , . :
. . .object View {
interface State {
var counter: Int
}
interface Methods {
fun showMessage(message: String)
}
}
interface Router {
fun toNext()
}
class Presenter : BasePresenter<View.State, View.Methods, Router>() {
override val viewStateProxy = object : View.State {
override var counter by state({ it::counter }, initial = 0)
}
override fun onEnter() {
viewStateProxy.counter = 1
viewMethods?.showMessage("Hello!")
router.toNext()
}
}
, , . , , . - . : Dagger, Retrofit Moxy.
Moxy . , view.
AddToEndSingleStrategy
view.
OneExecutionStrategy
, , view .
SkipStrategy
.
AddToEndSingleStrategy
Summer state
. .
, Kotlin , , .
interface View {
var counter: Int?
fun showMessage()
}
class Presenter : BasePresenter<View>() {
override val viewProxy = object : View {
override var counter by state({ it::counter }, initial = null)
override fun showMessage = event { it::showMessage }
}
}
abstract class BasePresenter<TView> {
fun event(
getAction: (TView) -> (() -> Unit)
) = Event(getAction)
}
class Event<TView>(
getAction: (TView) -> (() -> Unit)
) : () -> Unit
. :
interface View {
var counter: Int?
}
interface Events {
fun showMessage(message: String)
}
class Presenter : BasePresenter<View>() {
override val viewProxy = object : View {
override var counter by state({ it::counter }, initial = null)
}
val showMessage = event { it::showMessage }
}
, View . , , .
?
- -, — .
- . -, .
- .
– . - , . , , , . , . Kotlin , - . . , , , . , .
- . ?
Kotlin:
override fun showMessage(message: String) {
Toast.makeText(requireContext(), "message", Toast.LENGTH_LONG).show()
}
Kotlin:
override val showMessage = { message: String ->
Toast.makeText(requireContext(), "message", Toast.LENGTH_LONG).show()
}
Swift:
fun showMessage(message: String) {
printMessage(message)
}
Swift:
lazy var showMessage: (String) -> Void = { message in
self.printMessage(message)
}
(つ✧ω✧)つ
override val showMessage = { message: String -> Unit in
printMessage(message)
}
- . , . 5-6 , , .
№2.
view, . :
interface View {
val showMessage: () -> Unit
}
class Presenter : BasePresenter<View>() {
override val viewProxy = object : View {
override val showMessage = doOnlyWhenAttached { it.showMessage }
}
}
abstract class BasePresenter<TView> {
fun doOnlyWhenAttached(
getAction: (TView) -> (() -> Unit)
) = Event(getAction)
}
class Event<TView>(
action: (TView) -> (() -> Unit)
) : () -> Unit
. , Kotlin . vararg
, . view.
interface View {
val showMessage: (message: String) -> Unit
}
class Presenter : BasePresenter<View>() {
override val viewProxy = object : View {
override val showMessage = doOnlyWhenAttached { it.showMessage }
}
}
abstract class BasePresenter<TView> {
fun doOnlyWhenAttached(
getAction: (TView) -> (() -> Unit)
) = Event0(getAction)
fun <T1> doOnlyWhenAttached(
getAction: (TView) -> ((T1) -> Unit)
) = Event1(getAction)
}
class Event0<TView>(
action: (TView) -> (() -> Unit)
) : () -> Unit
class Event1<TView, T1>(
action: (TView) -> ((T1) -> Unit)
) : (T1) -> Unit
e: <...>/adev/presentation/View.kt: (10, 22): Type of 'showMessage' is not a subtype of the overridden property 'public abstract val showMessage: (message: String) -> Unit defined in adev.presentation.View'

Kotlin , . , Kotlin , . doOnlyWhenAttached
TView
, T1
. , .
"" – Event
2 :
TView
Event
interface View {
val showMessage: (message: String) -> Unit
}
class Presenter : BasePresenter<View>() {
override val viewProxy = object : View {
override val showMessage = event { it.showMessage }.doOnlyWhenAttached()
}
}
abstract class BasePresenter<TView> {
fun <TAction> event(getAction: (TView) -> TAction) = EventBuilder(getAction)
fun EventBuilder<TView, () -> Unit>.doOnlyWhenAttached() {
return Event0(this.getAction)
}
fun <T1> EventBuilder<TView, (T1) -> Unit>.doOnlyWhenAttached() {
return Event1(this.getAction)
}
}
inline class EventBuilder<TView, TAction>(
val getAction: (TView) -> TAction
)
class Event0<TView>(
action: (TView) -> (() -> Unit)
) : () -> Unit
class Event1<TView, T1>(
action: (TView) -> ((T1) -> Unit)
) : (T1) -> Unit
. shorthands . :
interface View {
val showMessage: (message: String) -> Unit
val showMessage1: (message: String) -> Unit
val showMessage2: (message: String) -> Unit
}
class Presenter : BasePresenter<View>() {
override val viewProxy = object : View {
override val showMessage = event { it.showMessage }.build(RepeatLastStrategy())
override val showMessage1 = event { it.showMessage1 }.doOnlyWhenAttached()
override val showMessage2 = event { it.showMessage2 }.doExactlyOnce()
}
}
, !
. , 30. , , production. 2- . , , !
Summer 5 production . 2 – . MaksimNovikov, metnyov deks1309 , . XanderZhu umpteenthdev mowenik iOS .
, Summer, . :
android.widget.View, UIView . , - . , . , .
interface View {}
class Presenter : SummerPresenter<View> {
override val viewProxy = object : View {}
val subPresenter = SubPresenter(
onAction = { doSomething() }
)
}
class Fragment : SummerFragment(R.layout.fragment), View {
private val presenter by bindPresenter { Presenter() }
private lateinit var popup: Popup
override fun onViewCreated(...) {
super.onViewCreated(...)
popup = Popup(presenter.subPresenter)
}
}
interface SubView {
var counter: Int
}
class SubPresenter(
private val onAction: () -> Unit
): SummerPresenter<SubView>() {
override val viewProxy = object : SubView {
override var counter by state({ it::counter }, initial = 0)
}
}
class Popup(
private val presenter: SubPresenter
) : <...>, SubView {
init {
bindPresenter { presenter }
}
}
- VueJS ReactJS.
sealed State
AddToEndSingleTagStrategy
Moxy, Summer state
sealed
.
sealed class ViewState {
object Loading : ViewState()
class Content(val counter) : ViewState()
}
interface View {
var state: ViewState
}
class Presenter : SummerPresenter<View>() {
override val viewProxy = object : View {
override var state by state({ it::state }, initial = ViewState.Loading)
}
}
MaksimNovikov .
didSet in Kotlin
Kotlin set
. didSet
didSetNotNull
, didSet
Swift.
:
data class Item(val id: Int, val count: Int)
interface View {
var items: List<Item>
}
class Presenter : SummerPresenter<View>() {
override val viewProxy = object : View {
override var items by state({ it::items }, initial = emptyList())
}
fun increment(id: Int) {
viewProxy.items = viewProxy.items.map { item ->
if (item.id == id)
item.copy(count = item.count + 1)
else
item
}
}
}
, view, . , state
, store
view .
Summer Kotlin/Multiplatform :
Kotlin/Multiplatform . iOS-, , , . , , . iOS 0. , .
Summer iOS-. XCode. Swift. Kotlin XCode TouchLab. , , iOS-. VIPER, Clean Swift .. MVP.
, Kotlin. Summer , unsafe casts , Kotlin . , , — iOS Swift view. .
, , APT, Summer, .
, viewProxy
boilerplate.
interface View {
var counter: Int
}
class Presenter : SummerPresenter<View>() {
override val viewProxy = object : View {
override var state by state({ it::counter }, initial = 0)
}
}
{ it::counter }
. , . , - . , lint .
viewstate
, , Swift. Kotlin didSet
didSetNotNull
view. Swift view . , , . nil
. — , , .
, , state
initial
, state
, event
RepeatLastStrategy
init
.
, Moxy Summer Summer Moxy . 15-20 . iOS Android- Summer 3-4 . , VIPER. ViewController-, iOS- . , Kotlin. iOS, , .
Anda juga dapat menerjemahkan 1-2 layar untuk mencoba. Kotlin memiliki interop yang cukup bagus dengan Swift, dan Swift tidak terlalu peduli dalam bahasa apa kode ini ditulis. Kelas-kelas yang ditulis di Kotlin terlihat Swift seolah-olah mereka ditulis dalam Objective-C dengan penjelasan kompatibilitas diletakkan di tempat yang tepat.
Kesimpulan
Terima kasih kepada semua orang yang membaca sampai akhir! Saya harap Anda belajar sesuatu yang baru tentang Kotlin untuk diri sendiri, dan mungkin bahkan mencoba Musim Panas . Saya akan sangat berterima kasih atas umpan balik yang membangun.