Создание новых объектов при каждом скролле. Правильное использование ViewHolder для повторного использования представлений.
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
public static class MyViewHolder extends RecyclerView.ViewHolder {
public TextView textView;
public MyViewHolder(View v) {
super(v);
textView = v.findViewById(R.id.textView);
}
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.my_text_view, parent, false);
return new MyViewHolder(v);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.textView.setText(myDataset[position]);
}
@Override
public int getItemCount() {
return myDataset.length;
}
}Загрузка изображений или обработка данных. Использование асинхронных задач и библиотек для загрузки изображений.
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.textView.setText(myDataset[position]);
Glide.with(holder.imageView.getContext())
.load(imageUrls[position])
.into(holder.imageView);
}
Загрузка больших изображений без сжатия. Использование библиотек Glide или Picasso.
Glide.with(context)
.load(url)
.into(imageView);
Сложные иерархии макетов. Использование простых макетов и ViewStub для отложенной загрузки.
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:contentDescription="@string/image_desc" />
<TextView
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/sample_text" />
</androidx.constraintlayout.widget.ConstraintLayout>
Перерисовка всего списка. Использование notifyItemInserted, notifyItemRemoved, notifyItemChanged для частичных обновлений.
adapter.notifyItemInserted(position);
adapter.notifyItemRemoved(position);
Повторная загрузка данных при каждом скролле. Кэширование данных с помощью LiveData.
LiveData<List<Item>> items = viewModel.getItems();
items.observe(this, new Observer<List<Item>>() {
@Override
public void onChanged(List<Item> items) {
adapter.setItems(items);
}
});
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥8
Является жадной коллекцией, что означает, что все операции над элементами выполняются немедленно и целиком. Когда вы применяете функции к списку, такие как
map, filter и т.д., все элементы проходят через каждую функцию сразу же. В данном примере все элементы списка numbers сначала умножаются на 2, затем фильтруются. Вся работа выполняется сразу для каждого элемента.val numbers = listOf(1, 2, 3, 4, 5)
val result = numbers
.map { it * 2 }
.filter { it > 5 }
println(result) // Output: [6, 8, 10]
Является ленивой коллекцией. Это означает, что элементы обрабатываются по мере необходимости. Функции, применяемые к последовательности, создают цепочку операций, которая выполняется только при обращении к элементам. В этом примере
numbers сначала преобразуется в Sequence. Операции map и filter создают цепочку, которая выполняется только при преобразовании обратно в List с помощью toList(). Это позволяет избежать лишних операций и обрабатывать элементы по мере необходимости.val numbers = listOf(1, 2, 3, 4, 5)
val result = numbers.asSequence()
.map { it * 2 }
.filter { it > 5 }
.toList()
println(result) // Output: [6, 8, 10]
List: Все элементы обрабатываются сразу при вызове функций.
Sequence: Элементы обрабатываются по мере необходимости, что может повысить эффективность.
List: Подходит для небольших коллекций, где выполнение всех операций сразу не критично.
Sequence: Эффективен для больших коллекций или длинных цепочек операций, так как уменьшает количество промежуточных коллекций.
List: Может использовать больше памяти из-за создания промежуточных коллекций.
Sequence: Уменьшает использование памяти, обрабатывая элементы по одному.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7👍5
Это компонент приложения, который выполняет долгосрочные операции в фоновом режиме и не предоставляет пользовательского интерфейса. Сервисы позволяют выполнять задачи, которые не требуют взаимодействия с пользователем, например, воспроизведение музыки, загрузка файлов, обработка данных и т.д.
Сервисы выполняют задачи в фоновом режиме, что позволяет не прерывать работу пользовательского интерфейса.
Сервисы не имеют пользовательского интерфейса. Они работают независимо от активности, которая может завершиться или быть приостановлена.
Сервисы предназначены для выполнения длительных операций, которые могут продолжаться даже после закрытия приложения.
Запускается с помощью метода
startService(). Выполняет свою задачу независимо и завершает работу сам, вызвав stopSelf(), или его можно остановить извне, вызвав stopService(). Загрузка файла в фоне.// Запуск сервиса
Intent intent = new Intent(this, MyService.class);
startService(intent);
// Остановка сервиса
stopService(intent);
Предоставляет интерфейс клиентам для взаимодействия с сервисом с помощью
bindService(). Связывается с компонентом приложения (например, Activity), и работает до тех пор, пока компонент не завершится. Сервис для взаимодействия с удаленной базой данных.// Привязка к сервису
Intent intent = new Intent(this, MyService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
// Отключение от сервиса
unbindService(serviceConnection);
Пример привязки к Bound Service в Activity:
public class MainActivity extends AppCompatActivity {
MyBoundService myService;
boolean isBound = false;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
MyBoundService.LocalBinder binder = (MyBoundService.LocalBinder) service;
myService = binder.getService();
isBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
isBound = false;
}
};
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, MyBoundService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if (isBound) {
unbindService(serviceConnection);
isBound = false;
}
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17🔥4
Он используется для обозначения кода, который никогда не завершится успешно. Понимание того, почему и как
Nothing можно подставлять везде, требует изучения его особенностей и применения.Nothing является подтипом любого другого типа в Kotlin. Это означает, что значение типа Nothing можно присвоить переменной любого типа.Тип
Nothing не имеет значений. Любая функция, которая возвращает Nothing, либо выбрасывает исключение, либо не завершает выполнение (например, бесконечный цикл).Функции, которые всегда выбрасывают исключение, могут быть объявлены с возвращаемым типом
Nothing.fun fail(message: String): Nothing {
throw IllegalArgumentException(message)
}Тип
Nothing используется для обозначения точек кода, которые не могут быть достигнуты. Например, после выбрасывания исключения выполнение кода не продолжается.val result: Int = fail("Error occurred") // Тип Nothing может быть присвоен переменной типа IntNothing может быть использован в выражениях, где требуется любой тип. Это позволяет писать более выразительный и безопасный код.fun process(value: Any?) {
val result = value ?: fail("Value is null") // fail возвращает Nothing, который совместим с любым типом
}В некоторых случаях
Nothing используется в библиотеках для обработки ошибок или в случаях, когда выполнение программы не может продолжаться.sealed class Result<out T>
class Success<out T>(val data: T) : Result<T>()
class Error(val exception: Throwable) : Result<Nothing>() // Error использует Nothing
Функция, выбрасывающая исключение
fun terminate(): Nothing {
throw RuntimeException("This function never returns")
}
fun main() {
val x: Int = terminate() // Можно присвоить переменной типа Int
}Использование
Nothing в условных выражениях:fun checkNotNull(value: String?): String {
return value ?: fail("Value is null") // Если value null, вызовется fail, возвращающий Nothing
}
fun main() {
val name: String = checkNotNull(null) // Ошибка: Value is null
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥3❤1
Имеется богатый набор коллекций, которые предоставляют различные способы хранения и управления данными. Коллекции в Kotlin можно разделить на две основные категории: неизменяемые (immutable) и изменяемые (mutable). В рамках этих категорий есть несколько типов коллекций, таких как списки, множества и карты.
Неизменяемый список, который позволяет хранить элементы в определенном порядке и допускает дублирование элементов.
val immutableList: List<String> = listOf("Apple", "Banana", "Cherry")Неизменяемое множество, которое не допускает дублирования элементов и не гарантирует сохранение порядка.
val immutableSet: Set<String> = setOf("Apple", "Banana", "Cherry")Неизменяемая карта, которая хранит пары ключ-значение. Ключи должны быть уникальными.
val immutableMap: Map<String, Int> = mapOf("Apple" to 1, "Banana" to 2, "Cherry" to 3)Изменяемый список, который позволяет добавлять, удалять и изменять элементы.
val mutableList: MutableList<String> = mutableListOf("Apple", "Banana", "Cherry")
mutableList.add("Date")Изменяемое множество, которое позволяет добавлять и удалять элементы.
val mutableSet: MutableSet<String> = mutableSetOf("Apple", "Banana", "Cherry")
mutableSet.add("Date")Изменяемая карта, которая позволяет добавлять, удалять и изменять пары ключ-значение.
val mutableMap: MutableMap<String, Int> = mutableMapOf("Apple" to 1, "Banana" to 2, "Cherry" to 3)
mutableMap["Date"] = 4Изменяемый список, основанный на массиве. Обеспечивает быстрый доступ по индексу.
val arrayList: ArrayList<String> = arrayListOf("Apple", "Banana", "Cherry")Изменяемое множество, основанное на хэш-таблице. Обеспечивает быструю проверку принадлежности.
val hashSet: HashSet<String> = hashSetOf("Apple", "Banana", "Cherry")Изменяемая карта, основанная на хэш-таблице. Обеспечивает быстрый доступ к значениям по ключу.
val hashMap: HashMap<String, Int> = hashMapOf("Apple" to 1, "Banana" to 2, "Cherry" to 3)Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🔥2🎉1
Причина: Создание новых объектов при каждом скролле приводит к значительным задержкам.
Решение: Используйте ViewHolder для повторного использования представлений.
class MyAdapter(private val myDataset: Array<String>) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
class MyViewHolder(v: View) : RecyclerView.ViewHolder(v) {
val textView: TextView = v.findViewById(R.id.textView)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val v = LayoutInflater.from(parent.context)
.inflate(R.layout.my_text_view, parent, false)
return MyViewHolder(v)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.textView.text = myDataset[position]
}
override fun getItemCount(): Int {
return myDataset.size
}
}Причина: Выполнение тяжелых операций в главном потоке приводит к блокировке пользовательского интерфейса.
Решение: Переносите тяжелые операции в асинхронные задачи или используйте библиотеки для асинхронной загрузки.
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.textView.text = myDataset[position]
Glide.with(holder.imageView.context)
.load(imageUrls[position])
.into(holder.imageView)
}Причина: Загрузка больших изображений в главном потоке может замедлить приложение.
Решение: Используйте библиотеки, такие как Glide или Picasso, которые автоматически обрабатывают загрузку и кэширование изображений.
Glide.with(context)
.load(url)
.into(imageView);
Причина: Сложные иерархии макетов или невидимые представления занимают больше памяти и времени на рендеринг.
Решение: Оптимизируйте макеты, минимизируйте количество вложенных представлений и используйте ViewStub для отложенной загрузки.
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:contentDescription="@string/image_desc" />
<TextView
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/imageView"
android:text="@string/sample_text" />
</androidx.constraintlayout.widget.ConstraintLayout>
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8
Добавляет элемент на вершину стека. Эта операция вставляет новый элемент в стек и делает его верхним элементом.
val stack = Stack<Int>()
stack.push(10) // Стек: [10]
stack.push(20) // Стек: [10, 20]
Удаляет и возвращает верхний элемент стека. Эта операция удаляет элемент, который находится на вершине стека, и возвращает его. Если стек пуст, обычно выбрасывается исключение (например,
EmptyStackException).val top = stack.pop() // top = 20, Стек: [10]
Возвращает верхний элемент стека без его удаления. Эта операция позволяет просмотреть верхний элемент стека без его удаления. Если стек пуст, обычно выбрасывается исключение.
val top = stack.peek() // top = 10, Стек: [10]
Ищет элемент в стеке и возвращает его позицию относительно вершины стека. Если элемент не найден, возвращает -1.
val position = stack.search(10) // position = 1
Пример использования стека
import java.util.Stack;
public class StackExample {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
// Добавление элементов (push)
stack.push(10);
stack.push(20);
stack.push(30);
// Просмотр верхнего элемента (peek)
System.out.println("Верхний элемент: " + stack.peek()); // Вывод: 30
// Удаление верхнего элемента (pop)
System.out.println("Удален элемент: " + stack.pop()); // Вывод: 30
System.out.println("Новый верхний элемент: " + stack.peek()); // Вывод: 20
// Проверка, пуст ли стек (isEmpty)
System.out.println("Стек пустой? " + stack.isEmpty()); // Вывод: false
// Размер стека (size)
System.out.println("Размер стека: " + stack.size()); // Вывод: 2
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥3❤1
ArrayList реализован на основе массива. Амортизированное O(1). Если массив не заполнен, элемент добавляется в конец списка. В случае, если массив заполнен, требуется выделение нового массива и копирование элементов, что занимает O(n) времени.
val arrayList = ArrayList<Int>()
arrayList.add(1) // Быстрая вставка в конец
O(n). Необходимо сдвинуть все элементы, начиная с позиции вставки, чтобы освободить место для нового элемента. Это требует времени, пропорционального количеству элементов после позиции вставки.
arrayList.add(0, 2) // Медленная вставка в начало
arrayList.add(1, 3) // Медленная вставка в середину
LinkedList реализован на основе узлов, где каждый узел содержит ссылку на следующий и/или предыдущий узел (в случае двусвязного списка).val linkedList = LinkedList<Int>()
linkedList.addFirst(1) // Быстрая вставка в начало
O(1) (если есть ссылка на последний узел) или O(n) (если необходимо пройти весь список). Если список двусвязный и хранится ссылка на последний элемент, вставка в конец осуществляется за O(1). В противном случае, требуется пройти весь список до конца.
linkedList.addLast(2) // Быстрая вставка в конец, если есть ссылка на последний узел
O(n). Необходимо пройти список до нужной позиции и изменить ссылки узлов.
linkedList.add(1, 3) // Медленная вставка в середину
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6
Это способ определения пользовательского интерфейса (UI) приложения, который описывает, как элементы интерфейса (виджеты) располагаются на экране. Макеты задаются с помощью XML-файлов или программно в коде.
Располагает дочерние элементы в виде одной строки или столбца (вертикально или горизонтально). Подходит для простых интерфейсов, где элементы должны быть расположены один за другим.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, World!" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click Me" />
</LinearLayout>
Располагает дочерние элементы относительно друг друга или относительно родительского контейнера. Подходит для более сложных интерфейсов, где элементы должны быть выровнены относительно других элементов
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, World!" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click Me"
android:layout_below="@id/textView" />
</RelativeLayout>
Предоставляет гибкую систему ограничения для размещения элементов относительно друг друга и границ контейнера. Это мощный и эффективный макет, который заменяет сложные вложенные макеты. Подходит для сложных интерфейсов, где требуется точное позиционирование и выравнивание элементов.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, World!"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click Me"
app:layout_constraintTop_toBottomOf="@id/textView"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥2
Это класс, который используется для хранения данных. Важной особенностью таких классов является автоматическая генерация некоторых методов, включая
componentN функции. Эти функции нужны для того, чтобы можно было легко получать значения свойств объекта данного класса. Здесь объявлен data class
Person с двумя свойствами: name и age. Когда создается объект person этого класса, мы можем использовать синтаксис деструктуризации для извлечения значений этих свойств. Внутренне это работает благодаря componentN функциям, которые автоматически создаются компилятором для каждого свойства. data class Person(val name: String, val age: Int)
fun main() {
val person = Person("Alice", 30)
// Использование componentN функций
val (name, age) = person
println("Name: $name, Age: $age")
}
component1 возвращает значение свойства name.component2 возвращает значение свойства age.Синтаксис деструктуризации (
val (name, age) = person) позволяет присвоить значения этих свойств соответствующим переменным, как если бы мы вручную вызывали person.component1() и person.component2().Вот как это могло бы выглядеть без синтаксиса деструктуризации:
И так, функции
componentN служат для облегчения доступа к свойствам data class, особенно при использовании синтаксиса деструктуризации.fun main() {
val person = Person("Alice", 30)
val name = person.component1()
val age = person.component2()
println("Name: $name, Age: $age")
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥1