Kotlin 소개: 인간을 위한 Android 프로그래밍
게시 됨: 2022-03-11완벽한 Android 세계에서 Java의 기본 언어는 정말 현대적이고 명확하며 우아합니다. 더 많이 하면 덜 쓸 수 있고, 새로운 기능이 나타날 때마다 개발자는 Gradle에서 버전을 올리기만 하면 사용할 수 있습니다. 그런 다음 아주 멋진 앱을 만드는 동안 완전히 테스트 가능하고 확장 가능하며 유지 관리할 수 있는 것처럼 보입니다. 우리의 활동은 너무 크고 복잡하지 않으며 많은 차이 없이 데이터베이스에서 웹으로 데이터 소스를 변경할 수 있습니다. 정말 좋은데요? 불행히도, 안드로이드 세계는 이상적이지 않습니다. Google은 여전히 완벽을 위해 노력하고 있지만 이상적인 세계는 존재하지 않는다는 것을 우리 모두 알고 있습니다. 따라서 우리는 Android 세계의 위대한 여정에서 스스로를 도와야 합니다.
Kotlin이란 무엇이며 왜 사용해야 하나요?
그래서, 첫 번째 언어. 나는 Java가 우아함이나 명료함의 대가가 아니며 현대적이지도 않고 표현적이지도 않다고 생각합니다. 단점은 Android N 이하에서는 여전히 Java 6(Java 7의 일부 작은 부분 포함)으로 제한된다는 것입니다. 개발자는 또한 RetroLambda를 첨부하여 코드에서 람다 식을 사용할 수 있습니다. 이는 RxJava를 사용하는 동안 매우 유용합니다. Android N 이상에서는 Java 8의 새로운 기능 중 일부를 사용할 수 있지만 여전히 오래되고 무거운 Java입니다. Android 개발자가 "iOS가 Swift에서 지원하는 것처럼 Android가 더 나은 언어를 지원했으면 합니다."라고 말하는 것을 종종 듣습니다. 그리고 null 안전, 람다 및 기타 많은 멋진 새 기능과 함께 아주 훌륭하고 간단한 언어를 사용할 수 있다고 말하면 어떻게 될까요? 코틀린에 오신 것을 환영합니다.
코틀린이란?
Kotlin은 JetBrains 팀에서 개발한 새로운 언어(Android용 Swift라고도 함)이며 현재 1.0.2 버전입니다. Android 개발에서 유용한 이유는 JVM 바이트 코드로 컴파일되고 JavaScript로도 컴파일될 수 있다는 것입니다. Java와 완벽하게 호환되며 Kotlin 코드를 Java 코드로 또는 그 반대로 간단히 변환할 수 있습니다(JetBrains의 플러그인 있음). 즉, Kotlin은 Java로 작성된 모든 프레임워크, 라이브러리 등을 사용할 수 있습니다. Android에서는 Gradle로 통합됩니다. 기존 Android 앱이 있고 전체 앱을 다시 작성하지 않고 Kotlin에서 새 기능을 구현하려는 경우 Kotlin에서 작성을 시작하기만 하면 작동합니다.
그러나 '훌륭한 새 기능'은 무엇입니까? 몇 가지를 나열하겠습니다.
선택적 및 명명된 함수 매개변수
fun createDate(day: Int, month: Int, year: Int, hour: Int = 0, minute: Int = 0, second: Int = 0) { print("TEST", "$day-$month-$year $hour:$minute:$second") }
다른 방법으로 createDate 메서드를 호출할 수 있습니다.
createDate(1,2,2016) prints: '1-2-2016 0:0:0' createDate(1,2,2016, 12) prints: '1-2-2016 12:0:0' createDate(1,2,2016, minute = 30) prints: '1-2-2016 0:30:0'
널 세이프티
변수가 null일 수 있으면 강제로 만들지 않는 한 코드가 컴파일되지 않습니다. 다음 코드에는 오류가 있습니다. nullableVar는 null일 수 있습니다.
var nullableVar: String? = “”; nullableVar.length;
컴파일하려면 null이 아닌지 확인해야 합니다.
if(nullableVar){ nullableVar.length }
또는 더 짧게:
nullableVar?.length
이렇게 하면 nullableVar가 null이면 아무 일도 일어나지 않습니다. 그렇지 않으면 유형 뒤에 물음표 없이 변수를 nullable이 아닌 것으로 표시할 수 있습니다.
var nonNullableVar: String = “”; nonNullableVar.length;
이 코드는 컴파일되고 nonNullableVar에 null을 할당하려는 경우 컴파일러는 오류를 표시합니다.
매우 유용한 Elvis 연산자도 있습니다.
var stringLength = nullableVar?.length ?: 0
그런 다음 nullableVar가 null인 경우(따라서 nullableVar?.length가 null을 반환함) stringLength의 값은 0이 됩니다.
가변 및 불변 변수
위의 예에서는 변수를 정의할 때 var를 사용합니다. 이것은 변경 가능하며 원할 때마다 다시 할당할 수 있습니다. 그 변수가 불변이기를 원한다면(많은 경우에 그래야 함) val(변수가 아닌 값으로)을 사용합니다.
val immutable: Int = 1
그 후에 컴파일러는 불변에 재할당하는 것을 허용하지 않습니다.
람다
우리는 모두 람다가 무엇인지 알고 있으므로 여기서는 Kotlin에서 람다가 사용하는 방법을 보여드리겠습니다.
button.setOnClickListener({ view -> Log.d("Kotlin","Click")})
또는 함수가 유일한 또는 마지막 인수인 경우:
button.setOnClickListener { Log.d("Kotlin","Click")}
확장
확장은 매우 유용한 언어 기능입니다. 덕분에 기존 클래스가 최종이거나 소스 코드에 액세스할 수 없는 경우에도 기존 클래스를 "확장"할 수 있습니다.
예를 들어, editText.text.toString()을 매번 작성하는 대신 편집 텍스트에서 문자열 값을 얻으려면 다음 함수를 작성할 수 있습니다.
fun EditText.textValue(): String{ return text.toString() }
또는 더 짧게:
fun EditText.textValue() = text.toString()
이제 EditText의 모든 인스턴스에서:
editText.textValue()
또는 동일한 결과를 반환하는 속성을 추가할 수 있습니다.
var EditText.textValue: String get() = text.toString() set(v) {setText(v)}
연산자 오버로딩
객체를 더하거나, 곱하거나, 비교할 때 때때로 유용합니다. Kotlin은 이항 연산자(플러스, 마이너스, plusAssign, 범위 등), 배열 연산자(가져오기, 설정, 범위 가져오기, 범위 설정), 등호 및 단항 연산(+a, -a 등)의 오버로딩을 허용합니다.
데이터 클래스
copy, equals, hashCode 및 toString의 세 가지 속성을 사용하여 Java에서 User 클래스를 구현하려면 몇 줄의 코드가 필요합니까? Kaotlin에서는 한 줄만 필요합니다.
data class User(val name: String, val surname: String, val age: Int)
이 데이터 클래스는 equals(), hashCode() 및 copy() 메서드와 사용자를 다음과 같이 출력하는 toString()을 제공합니다.
User(name=John, surname=Doe, age=23)
데이터 클래스는 Kotlin 문서에서 볼 수 있는 몇 가지 다른 유용한 기능과 속성도 제공합니다.
Anko 확장
Butterknife 또는 Android 확장 프로그램을 사용하지 않습니까? 이 라이브러리를 사용할 필요도 없고 XML로 보기를 선언한 후 ID별로 코드에서 사용하면(예: C#의 XAML):
<Button android: android:layout_width="match_parent" android:layout_height="wrap_content" />
loginBtn.setOnClickListener{}
Kotlin에는 매우 유용한 Anko 확장이 있으며 이를 사용하면 활동에 loginBtn이 무엇인지 말할 필요가 없으며 xml을 "가져오기"만 하면 알 수 있습니다.
import kotlinx.android.synthetic.main.activity_main.*
Anko에는 활동 시작, 건배 표시 등을 포함하여 다른 많은 유용한 기능이 있습니다. 이것은 Anko의 주요 목표가 아닙니다. 코드에서 레이아웃을 쉽게 생성하도록 설계되었습니다. 따라서 프로그래밍 방식으로 레이아웃을 생성해야 하는 경우 이것이 가장 좋은 방법입니다.
이것은 Kotlin의 짧은 보기일 뿐입니다. Antonio Leiva의 블로그와 그의 책 - Android 개발자를 위한 Kotlin, 그리고 물론 공식 Kotlin 사이트를 읽는 것이 좋습니다.
MVP란 무엇이며 그 이유는 무엇입니까?
훌륭하고 강력하고 명확한 언어로는 충분하지 않습니다. 좋은 아키텍처 없이 모든 언어로 지저분한 앱을 작성하는 것은 매우 쉽습니다. Android 개발자(대부분 시작하는 개발자이지만 고급 개발자도 있음)는 주변의 모든 것에 대한 책임을 Activity에 부여하는 경우가 많습니다. Activity(또는 Fragment 또는 기타 보기)는 데이터를 다운로드하고, 저장하기 위해 전송하고, 이를 표시하고, 사용자 상호 작용에 응답하고, 데이터를 편집하고, 모든 하위 보기를 관리합니다. . . 그리고 종종 훨씬 더. 액티비티나 프래그먼트와 같은 불안정한 객체에는 너무 많습니다(화면을 회전하기에 충분하고 액티비티가 '안녕...'이라고 말합니다).
아주 좋은 아이디어는 뷰에서 책임을 분리하고 가능한 한 어리석게 만드는 것입니다. 보기(활동, 조각, 사용자 정의 보기 또는 화면에 데이터를 표시하는 모든 것)는 하위 보기 관리에 대해서만 책임을 져야 합니다. 보기에는 모델과 통신하고 수행해야 할 작업을 알려주는 발표자가 있어야 합니다. 간단히 말해서 이것은 Model-View-Presenter 패턴입니다(저의 경우 레이어 간의 연결을 표시하려면 Model-Presenter-View라는 이름을 지정해야 합니다).
“이봐, 나도 그런 걸 알아, MVC라고 해!” - 생각 안 했어? 아니요, MVP는 MVC와 다릅니다. MVC 패턴에서 뷰는 모델과 통신할 수 있습니다. MVP를 사용하는 동안 이 두 계층 간의 통신을 허용하지 않습니다. View가 Model과 통신할 수 있는 유일한 방법은 Presenter를 통하는 것입니다. View가 Model에 대해 알고 있는 유일한 것은 데이터 구조일 수 있습니다. 보기는 예를 들어 사용자를 표시하는 방법을 알고 있지만 언제인지는 모릅니다. 다음은 간단한 예입니다.
View는 “나는 Activity이고 두 개의 EditText와 한 개의 Button이 있습니다. 누군가 버튼을 클릭하면 발표자에게 말하고 EditText의 값을 전달해야 합니다. 그게 다야, 다음 클릭을 하거나 발표자가 무엇을 해야 할지 알려줄 때까지 잠을 잘 수 있습니다.”
Presenter는 어딘가에 View가 있다는 것을 알고 이 View가 수행할 수 있는 작업을 알고 있습니다. 그는 또한 두 개의 문자열을 수신할 때 이 두 개의 문자열에서 User를 생성하고 저장하기 위해 모델에 데이터를 보내고 저장이 성공하면 뷰에 '성공 정보 표시'를 알려야 한다는 것도 알고 있습니다.
모델은 데이터가 있는 위치, 저장해야 하는 위치 및 데이터에 대해 수행해야 하는 작업만 알고 있습니다.
MVP로 작성된 응용 프로그램은 테스트, 유지 관리 및 재사용이 쉽습니다. 순수한 발표자는 Android 플랫폼에 대해 아무것도 몰라야 합니다. 순수한 Java(또는 우리의 경우 Kotlin) 클래스여야 합니다. 덕분에 발표자를 다른 프로젝트에서 재사용할 수 있습니다. 또한 Model, View 및 Presenter를 별도로 테스트하여 단위 테스트를 쉽게 작성할 수도 있습니다.
약간의 여백: MVP는 애플리케이션을 훨씬 더 유연하고 멋지게 아키텍처로 만들기 위해 Uncle Bob's Clean Architecture의 일부가 되어야 합니다. 다음 시간에 그것에 대해 작성하려고 합니다.
MVP 및 Kotlin이 포함된 샘플 앱
이론은 충분합니다. 코드를 살펴보겠습니다! 자, 간단한 앱을 만들어 보겠습니다. 이 앱의 주요 목표는 사용자를 만드는 것입니다. 첫 번째 화면에는 두 개의 EditText(이름 및 성)와 하나의 버튼(저장)이 있습니다. 이름과 성을 입력하고 '저장'을 클릭하면 앱에 '사용자가 저장되었습니다'가 표시되고 저장된 이름과 성이 표시되는 다음 화면으로 이동해야 합니다. 이름이나 성이 비어 있는 경우 앱은 사용자를 저장하지 않아야 하며 무엇이 잘못되었는지 나타내는 오류를 표시해야 합니다.
Android Studio 프로젝트를 생성한 후 가장 먼저 해야 할 일은 Kotlin을 설정하는 것입니다. Kotlin 플러그인을 설치해야 하며, 재시작 후 Tools > Kotlin에서 'Configure Kotlin in Project'를 클릭할 수 있습니다. IDE는 Kotlin 종속성을 Gradle에 추가합니다. 기존 코드가 있는 경우 (Ctrl+Shift+Alt+K 또는 코드 > Java 파일을 Kotlin으로 변환)을 통해 Kotlin으로 쉽게 변환할 수 있습니다. 문제가 발생하여 프로젝트가 컴파일되지 않거나 Gradle에서 Kotlin이 표시되지 않는 경우 GitHub에서 사용 가능한 앱 코드를 확인할 수 있습니다.
이제 프로젝트가 있으므로 첫 번째 보기인 CreateUserView를 만들어 시작하겠습니다. 이 보기에는 앞에서 언급한 기능이 있어야 하므로 이에 대한 인터페이스를 작성할 수 있습니다.
interface CreateUserView : View { fun showEmptyNameError() /* show error when name is empty */ fun showEmptySurnameError() /* show error when surname is empty */ fun showUserSaved() /* show user saved info */ fun showUserDetails(user: User) /* show user details */ }
보시다시피 Kotlin은 함수 선언에서 Java와 유사합니다. 그것들은 모두 아무것도 반환하지 않는 함수이며 마지막에는 하나의 매개 변수가 있습니다. 이것이 차이점이며 매개변수 유형은 이름 뒤에 옵니다. View 인터페이스는 Android에서 가져온 것이 아니라 간단하고 비어 있는 인터페이스입니다.

interface View
Basic Presenter의 인터페이스에는 View 유형의 속성이 있어야 하며 적어도 메서드(예: onDestroy)에서 이 속성이 null로 설정되어야 합니다.
interface Presenter<T : View> { var view: T? fun onDestroy(){ view = null } }
여기에서 또 다른 Kotlin 기능을 볼 수 있습니다. 인터페이스에서 속성을 선언하고 거기에서 메서드를 구현할 수도 있습니다.
CreateUserView는 CreateUserPresenter와 통신해야 합니다. 이 발표자에게 필요한 유일한 추가 기능은 두 개의 문자열 인수가 있는 saveUser입니다.
interface CreateUserPresenter<T : View>: Presenter<T> { fun saveUser(name: String, surname: String) }
우리는 또한 모델 정의가 필요합니다. 이전 데이터 클래스에서 언급했습니다.
data class User(val name: String, val surname: String)
모든 인터페이스를 선언한 후 구현을 시작할 수 있습니다.
CreateUserPresenter는 CreateUserPresenterImpl에서 구현됩니다.
class CreateUserPresenterImpl(override var view: CreateUserView?): CreateUserPresenter<CreateUserView> { override fun saveUser(name: String, surname: String) { } }
클래스 정의가 있는 첫 번째 줄:
CreateUserPresenterImpl(override var view: CreateUserView?)
생성자이므로 인터페이스에 정의된 뷰 속성을 할당하는 데 사용합니다.
CreateUserView 구현인 MainActivity에는 CreateUserPresenter에 대한 참조가 필요합니다.
class MainActivity : AppCompatActivity(), CreateUserView { private val presenter: CreateUserPresenter<CreateUserView> by lazy { CreateUserPresenterImpl(this) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) saveUserBtn.setOnClickListener{ presenter.saveUser(userName.textValue(), userSurname.textValue()) /*use of textValue() extension, mentioned earlier */ } } override fun showEmptyNameError() { userName.error = getString(R.string.name_empty_error) /* it's equal to userName.setError() - Kotlin allows us to use property */ } override fun showEmptySurnameError() { userSurname.error = getString(R.string.surname_empty_error) } override fun showUserSaved() { toast(R.string.user_saved) /* anko extension - equal to Toast.makeText(this, R.string.user_saved, Toast.LENGTH_LONG) */ } override fun showUserDetails(user: User) { } override fun onDestroy() { presenter.onDestroy() } }
수업을 시작할 때 발표자를 다음과 같이 정의했습니다.
private val presenter: CreateUserPresenter<CreateUserView> by lazy { CreateUserPresenterImpl(this) }
불변(val)으로 정의되며, 처음 필요할 때 할당되는 지연 대리자에 의해 생성됩니다. 또한 null이 아닐 것이라고 확신합니다(정의 후 물음표 없음).
사용자가 저장 버튼을 클릭하면 View는 EditTexts 값과 함께 정보를 Presenter로 보냅니다. 그런 일이 발생하면 사용자가 저장되어야 하므로 Presenter(및 일부 모델 기능)에서 saveUser 메서드를 구현해야 합니다.
override fun saveUser(name: String, surname: String) { val user = User(name, surname) when(UserValidator.validateUser(user)){ UserError.EMPTY_NAME -> view?.showEmptyNameError() UserError.EMPTY_SURNAME -> view?.showEmptySurnameError() UserError.NO_ERROR -> { UserStore.saveUser(user) view?.showUserSaved() view?.showUserDetails(user) } } }
사용자가 생성되면 유효성을 확인하기 위해 UserValidator로 전송됩니다. 그런 다음 유효성 검사 결과에 따라 적절한 메소드가 호출됩니다. when() {} 구문은 Java의 switch/case와 동일합니다. 그러나 더 강력합니다. Kotlin은 'case'에 enum 또는 int를 사용할 수 있을 뿐만 아니라 범위, 문자열 또는 객체 유형도 사용할 수 있습니다. 모든 가능성을 포함하거나 else 표현식이 있어야 합니다. 여기에서는 모든 UserError 값을 다룹니다.
view?.showEmptyNameError()(보기 뒤에 물음표가 있음)를 사용하여 NullPointer로부터 보호됩니다. View는 onDestroy 메서드에서 null이 될 수 있으며 이 구성에서는 아무 일도 일어나지 않습니다.
User 모델에 오류가 없으면 UserStore에 저장하도록 지시한 다음 View에 성공을 표시하고 세부 정보를 표시하도록 지시합니다.
앞서 언급했듯이 몇 가지 모델을 구현해야 합니다.
enum class UserError { EMPTY_NAME, EMPTY_SURNAME, NO_ERROR } object UserStore { fun saveUser(user: User){ //Save user somewhere: Database, SharedPreferences, send to web... } } object UserValidator { fun validateUser(user: User): UserError { with(user){ if(name.isNullOrEmpty()) return UserError.EMPTY_NAME if(surname.isNullOrEmpty()) return UserError.EMPTY_SURNAME } return UserError.NO_ERROR } }
여기서 가장 흥미로운 것은 UserValidator입니다. 객체 단어를 사용하여 스레드, 개인 생성자 등에 대한 걱정 없이 싱글톤 클래스를 만들 수 있습니다.
다음으로 - validateUser(user) 메서드에는 with(user) {} 표현식이 있습니다. 이러한 블록 내의 코드는 개체의 컨텍스트에서 실행되며 이름과 성은 사용자 속성으로 전달됩니다.
또 다른 작은 것이 있습니다. enum에서 UserValidator까지 위의 모든 코드는 정의가 하나의 파일에 배치됩니다(User 클래스의 정의도 여기에 있음). Kotlin은 각 공개 클래스를 단일 파일에 포함하도록 강요하지 않습니다(또는 클래스 이름을 정확히 파일로 지정). 따라서 관련 코드의 짧은 부분(데이터 클래스, 확장, 함수, 상수 - Kotlin은 함수 또는 상수에 대한 클래스가 필요하지 않음)이 있는 경우 프로젝트의 모든 파일에 퍼뜨리는 대신 하나의 단일 파일에 배치할 수 있습니다.
사용자가 저장되면 앱이 이를 표시해야 합니다. 다른 보기가 필요합니다. Android 보기, 사용자 정의 보기, 조각 또는 활동이 될 수 있습니다. 저는 활동을 선택했습니다.
이제 UserDetailsView 인터페이스를 정의해 보겠습니다. 사용자를 표시할 수 있지만 사용자가 없을 때도 오류가 표시되어야 합니다.
interface UserDetailsView { fun showUserDetails(user: User) fun showNoUserError() }
다음으로 UserDetailsPresenter. 사용자 속성이 있어야 합니다.
interface UserDetailsPresenter<T: View>: Presenter<T> { var user: User? }
이 인터페이스는 UserDetailsPresenterImpl에서 구현됩니다. 사용자 속성을 재정의해야 합니다. 이 속성이 할당될 때마다 사용자는 보기에서 새로 고쳐져야 합니다. 이를 위해 속성 설정자를 사용할 수 있습니다.
class UserDetailsPresenterImpl(override var view: UserDetailsView?): UserDetailsPresenter<UserDetailsView> { override var user: User? = null set(value) { field = value if(field != null){ view?.showUserDetails(field!!) } else { view?.showNoUserError() } } }
UserDetailsView 구현인 UserDetailsActivity는 매우 간단합니다. 이전과 마찬가지로 지연 로딩으로 생성된 프리젠터 객체가 있습니다. 표시할 사용자는 인텐트를 통해 전달되어야 합니다. 현재로서는 작은 문제가 하나 있으며 잠시 후에 해결하겠습니다. 의도에서 사용자가 있을 때 View는 이를 발표자에게 할당해야 합니다. 그 후, 사용자는 화면에서 새로 고침됩니다. 또는 null인 경우 오류가 표시됩니다(활동은 완료되지만 발표자는 이에 대해 알지 못합니다).
class UserDetailsActivity: AppCompatActivity(), UserDetailsView { private val presenter: UserDetailsPresenter<UserDetailsView> by lazy { UserDetailsPresenterImpl(this) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_user_details) val user = intent.getParcelableExtra<User>(USER_KEY) presenter.user = user } override fun showUserDetails(user: User) { userFullName.text = "${user.name} ${user.surname}" } override fun showNoUserError() { toast(R.string.no_user_error) finish() } override fun onDestroy() { presenter.onDestroy() } }
인텐트를 통해 객체를 전달하려면 이 객체가 Parcelable 인터페이스를 구현해야 합니다. 이것은 매우 '더러운' 작업입니다. 개인적으로 나는 모든 CREATOR, 속성, 저장, 복원 등으로 인해 이 작업을 수행하는 것을 싫어합니다. 다행히도 적절한 플러그인인 Parcelable for Kotlin이 있습니다. 설치 후 클릭 한 번으로 Parcelable을 생성할 수 있습니다.
마지막으로 할 일은 MainActivity에서 showUserDetails(user: User)를 구현하는 것입니다.
override fun showUserDetails(user: User) { startActivity<UserDetailsActivity>(USER_KEY to user) /* anko extension - starts UserDetailsActivity and pass user as USER_KEY in intent */ }
그리고 그게 전부입니다.
사용자를 저장하는 간단한 앱이 있습니다(실제로 저장되지 않지만 발표자나 보기를 건드리지 않고 이 기능을 추가할 수 있음). 화면에 표시합니다. 앞으로 사용자가 화면에 표시되는 방식을 변경하려는 경우(예: 두 개의 활동에서 하나의 활동에서 두 개의 조각으로 또는 두 개의 사용자 정의 보기로) 변경 사항은 View 클래스에서만 이루어집니다. 물론 기능이나 모델의 구조를 변경하지 않는 경우입니다. View가 정확히 무엇인지 모르는 발표자는 변경할 필요가 없습니다.
무엇 향후 계획?
우리 앱에서는 활동이 생성될 때마다 Presenter가 생성됩니다. Presenter가 활동 인스턴스에서 지속되어야 하는 경우 이 접근 방식 또는 그 반대는 인터넷 전반에 걸쳐 많은 논의의 주제입니다. 저에게는 앱, 해당 요구 사항 및 개발자에 따라 다릅니다. 때로는 발표자를 파괴하는 것이 더 나을 때도 있고 그렇지 않을 때도 있습니다. 하나를 유지하기로 결정했다면 매우 흥미로운 기술은 이를 위해 LoaderManager를 사용하는 것입니다.
앞서 언급했듯이 MVP는 Uncle Bob's Clean 아키텍처의 일부여야 합니다. 게다가, 훌륭한 개발자는 활동에 발표자 종속성을 주입하기 위해 Dagger를 사용해야 합니다. 또한 향후 코드를 유지 관리, 테스트 및 재사용하는 데 도움이 됩니다. 현재 Kotlin은 Dagger(공식 릴리스 이전에는 쉽지 않았음) 및 기타 유용한 Android 라이브러리와 매우 잘 작동합니다.
마무리
저에게 Kotlin은 훌륭한 언어입니다. 현대적이고 명확하며 표현력이 뛰어나면서도 여전히 훌륭한 사람들에 의해 개발되고 있습니다. 또한 모든 Android 기기 및 버전에서 새 릴리스를 사용할 수 있습니다. Java에 대해 나를 화나게 만드는 것이 무엇이든 Kotlin은 개선되었습니다.
물론 내가 말했듯이 이상적인 것은 없습니다. Kotlin에도 몇 가지 단점이 있습니다. 최신 gradle 플러그인 버전(주로 알파 또는 베타)은 이 언어에서 제대로 작동하지 않습니다. 많은 사람들이 빌드 시간이 순수한 Java보다 약간 더 길고 apk에 추가 MB가 있다고 불평합니다. 그러나 Android Studio와 Gradle은 여전히 개선되고 있으며 휴대전화에는 앱을 위한 공간이 점점 더 많아지고 있습니다. 이것이 내가 Kotlin이 모든 Android 개발자에게 매우 좋은 언어가 될 수 있다고 믿는 이유입니다. 시도해 보고 아래의 의견 섹션에서 귀하의 생각을 공유하십시오.
샘플 앱의 소스 코드는 Github에서 사용할 수 있습니다. github.com/tomaszczura/AndroidMVPKotlin