Использование fragments и устаревших view - это не ошибка, а понимание работы их жизненного цикла - основа андроид разработки и один из главных вопросов на собеседовании. Если что, у компонентов композ те же состояния (Можно почитать про LocalLifecycleOwner), поэтому тогда уж вместо "ха-ха view сложно, а композ легко - учите композ" лучше говорить "ха-ха, разработка сложно, учитесь пользоваться агентами"
Попытался использовать код из примера, и программа не хочет завершаться, а через раз вообще NPE вылетает. Может, я что-то делаю не так или Вы что-то не указали в описании? Подскажите пожалуйста
Попытался использовать, в итоге через раз NullPointerException выскакивает, а если не выскакивает, то программа просто висит и не завершается. Подскажите пожалуйста!
Грузить данные во ViewModel нужно через AssistedInject (Hilt) или parametersOf (koin) и т.п. в подобных фреймворках в первичный конструктор ViewModel, а создание модели без данных, и загрузка их после создания - костыль, за который нужно бить по рукам)
Далее: 1 способ: loadInitialData имеет внутри launch - coroutineScope, и LaunchedEffect аналогично. Профит от launch { launch {} } буквально?
Далее: Грузить контакты, "Пользователь возвращается на экран "contacts_list" и видит удаленный контакт в списке, поскольку вьюмодель уже создана и init блок больше не отрабатывает." - Для таких ситуация существует Flow. Нужно брать из него данные в экране списка контактов и тогда там всегда будет актуальная информация. Конакты сохраняются в бд: если это Room, в нем можно возвращать тип Flow<List<T>>, а во viewModel и\или на экране подписываться с помощью Flow<List<T>>.collect {}. Тогда операции insert\delete\update будут выполняться штатно и без каких-либо дополнительных костылей
import com.google.gson.GsonBuilder
import com.google.gson.annotations.SerializedName
import okhttp3.ResponseBody
import retrofit2.Retrofit
import retrofit2.http.GET
data class ResponseWrapper(
@SerializedName("version") val version: String,
@SerializedName("reqId") val reqId: String,
@SerializedName("status") val status: String,
@SerializedName("sig") val sig: String,
@SerializedName("table") val table: Table
)
data class Table(
@SerializedName("cols") val cols: List<Column>,
@SerializedName("rows") val rows: List<Row>,
@SerializedName("parsedNumHeaders") val parsedNumHeaders: Int
)
data class Column(
@SerializedName("id") val id: String,
@SerializedName("label") val label: String,
@SerializedName("type") val type: String
)
data class Row(
@SerializedName("c") val cells: List<Cell?>
)
data class Cell(
@SerializedName("v") val value: String
)
interface GSheetsService {
@GET("gviz/tq?tqx=out:json")
suspend fun getSheetData(): ResponseBody
}
fun String.dataToJsonString(): String =
substringAfter("Query.setResponse(").let {
it.substring(0, it.lastIndex - 1)
}
fun String.getResponseFromJson(): ResponseWrapper =
GsonBuilder().setLenient().create()
.fromJson(this, ResponseWrapper::class.java)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val gSService = Retrofit.Builder()
.baseUrl(
"https://docs.google.com/spreadsheets/d/<ID документа>/"
).build().create(GSheetsService::class.java)
lifecycleScope.launch(Dispatchers.IO) {
val response = gSService.getSheetData().string().dataToJsonString().getResponseFromJson()
Log.d("response", "$response")
}
}
Ну и конечно же, я не говорю про разрешение на использование интернета)
Surf что скажете?)
А когда закончите?
Использование fragments и устаревших view - это не ошибка, а понимание работы их жизненного цикла - основа андроид разработки и один из главных вопросов на собеседовании. Если что, у компонентов композ те же состояния (Можно почитать про LocalLifecycleOwner), поэтому тогда уж вместо "ха-ха view сложно, а композ легко - учите композ" лучше говорить "ха-ха, разработка сложно, учитесь пользоваться агентами"
Зачем типобезопасную навигацию изобрели ещё раз?
Будет ли про рустор параграф? Очень интересно, и, думаю, актуально для других читателей тоже
Очень классная, подробная статья!
Попытался использовать код из примера, и программа не хочет завершаться, а через раз вообще NPE вылетает. Может, я что-то делаю не так или Вы что-то не указали в описании? Подскажите пожалуйста
Попытался использовать, в итоге через раз NullPointerException выскакивает, а если не выскакивает, то программа просто висит и не завершается. Подскажите пожалуйста!
Добрый вечер! Спасибо большое, верно подмечено! Будет добавлено!
Мой дорогой друг, удобство - это довольно абстрактное понятие, и у каждого оно своё, как и вкус, о котором я сказал выше)
Дело вкуса) Консерватизм имеет место быть!
Огромное спасибо за совет! Приму к сведению!
Грузить данные во ViewModel нужно через AssistedInject (Hilt) или parametersOf (koin) и т.п. в подобных фреймворках в первичный конструктор ViewModel, а создание модели без данных, и загрузка их после создания - костыль, за который нужно бить по рукам)
Далее: 1 способ:
loadInitialDataимеет внутри launch - coroutineScope, и LaunchedEffect аналогично. Профит от launch { launch {} } буквально?Далее: Грузить контакты, "Пользователь возвращается на экран
"contacts_list"и видит удаленный контакт в списке, поскольку вьюмодель уже создана и init блок больше не отрабатывает." - Для таких ситуация существует Flow. Нужно брать из него данные в экране списка контактов и тогда там всегда будет актуальная информация. Конакты сохраняются в бд: если это Room, в нем можно возвращать тип Flow<List<T>>, а во viewModel и\или на экране подписываться с помощью Flow<List<T>>.collect {}. Тогда операции insert\delete\update будут выполняться штатно и без каких-либо дополнительных костылейБлагодарю за замечание! Проверил и обновил!
От обновлений не сбежишь, я всё равно тебя настигну😏😏😏
Благодарю за замечание, обновил!
Будет ли часть про хранение данных? Очень интересно!
Ну и конечно же, я не говорю про разрешение на использование интернета)
Да, сейчас проверил, дошел до 12000 строк, дальше надоело)
Строки размером по 8 столбцов