Практическое задание
Нужно объединить ранее сделанные Android и iOS приложения в единый репозиторий, добавить модуль общего кода и перенести из Android и iOS логику работы с сетью и хранением токена в общий код
Во время работы над практическим заданием настоятельно рекомендуем обращаться к разделу Памятки для разработчика
Функциональные возможности
Остаются те же самые:
- Авторизация пользователя (personal access token)
- Просмотр списка репозиториев пользователя (первые 10)
- Просмотр детальной информации выбранного репозитория
- статистика (forks, stars, watchers)
- ссылка на web страницу репозитория
- лицензия
- readme
Технические требования
- Использовать multiplatform-settings для работы с хранилищем устройства
- Логика хранения данных должна находиться в common коде
- Логика работы с сетью должна находиться в common коде
- Для работы с сетью использовать Ktor Client 1.6.8
- При перезапуске приложения авторизация должна сохраняться
- Использовать локализацию для всех строк, показываемых пользователю
- Использовать векторную графику везде, где это возможно
- Обеспечить поддержку Android API 21
- Обеспечить поддержку iOS 13.0
Классы приложения
Чтобы использовать suspend
функции в общем коде, необходимо добавить аннотацию @Throws
. Благодаря этой аннотации, компилятор Kotlin/Native сгенерирует функцию с completion
для iOS
common code:
class AppRepository {
@Throws(Exception::class)
suspend fun getRepositories(): List<Repo> {
// TODO:
}
@Throws(Exception::class)
suspend fun getRepository(repoId: String): RepoDetails {
// TODO:
}
@Throws(Exception::class)
suspend fun getRepositoryReadme(
ownerName: String,
repositoryName: String,
branchName: String
): String {
// TODO:
}
@Throws(Exception::class)
suspend fun signIn(token: String): UserInfo {
// TODO:
}
// TODO:
}
class KeyValueStorage {
var authToken: String?
}
android app:
class MainActivity: AppCompatActivity {
// TODO:
}
class AuthFragment: Fragment {
// TODO:
}
class RepositoriesListFragment: Fragment {
// TODO:
}
class DetailInfoFragment: Fragment {
// TODO:
}
class AuthViewModel {
val token: MutableLiveData<String>
val state: LiveData<State>
val actions: Flow<Action>
fun onSignButtonPressed() {
// TODO:
}
sealed interface State {
object Idle : State
object Loading : State
data class InvalidInput(val reason: String) : State
}
sealed interface Action {
data class ShowError(val message: String) : Action
object RouteToMain : Action
}
// TODO:
}
class RepositoryInfoViewModel {
val state: LiveData<State>
sealed interface State {
object Loading : State
data class Error(val error: String) : State
data class Loaded(
val githubRepo: Repo,
val readmeState: ReadmeState
) : State
}
sealed interface ReadmeState {
object Loading : ReadmeState
object Empty : ReadmeState
data class Error(val error: String) : ReadmeState
data class Loaded(val markdown: String) : ReadmeState
}
// TODO:
}
class RepositoriesListViewModel {
val state: LiveData<State>
sealed interface State {
object Loading : State
data class Loaded(val repos: List<Repo>) : State
data class Error(val error: String) : State
object Empty : State
}
// TODO:
}
ios app:
class RepositoriesListViewController: UIViewController {
// TODO:
}
class RepositoryDetailInfoViewController: UIViewController {
// TODO:
}
class AuthViewController: UIViewController {
// TODO:
}
Диаграмма классов
На графе отображена зависимость компонентов KMM приложения друг от друга, цветами выделены подграфы:
Фиолетовый - Common, Зеленый - Android, Синий - iOS
classDiagram
class AppRepository:::common
class KeyValueStorage:::common
class MainActivity:::android
class AuthFragment:::android
class RepositoriesListFragment:::android
class DetailInfoFragment:::android
class AuthViewModel:::android
class RepositoryInfoViewModel:::android
class RepositoriesListViewModel:::android
class KeyValueStorage:::android
MainActivity --> AuthFragment
MainActivity --> RepositoriesListFragment
MainActivity --> DetailInfoFragment
AuthFragment --> AuthViewModel
RepositoriesListFragment --> RepositoriesListViewModel
DetailInfoFragment --> RepositoryInfoViewModel
RepositoryInfoViewModel --> AppRepository
AuthViewModel --> AppRepository
RepositoriesListViewModel --> AppRepository
AppRepository --> KeyValueStorage
class RepositoriesListViewController:::ios
class RepositoryDetailInfoViewController:::ios
class AuthViewController:::ios
RepositoriesListViewController --> AppRepository
RepositoryDetailInfoViewController --> AppRepository
AuthViewController --> AppRepository
Материалы: