Переменные по умолчанию не могут быть
null, что предотвращает NullPointerException.var a: String = "abc"
var b: String? = "abc"
b = null // Допустимо
Разделение на изменяемые и неизменяемые коллекции.
val list: List<String> = listOf("a", "b", "c") // Неизменяемый список
val mutableList: MutableList<String> = mutableListOf("a", "b", "c") // Изменяемый список Автоматическое создание методов
equals(), hashCode(), и toString().data class User(val name: String, val age: Int)
Автоматическое приведение типа после проверки с помощью
is.fun demo(x: Any) {
if (x is String) {
println(x.length)
}
} Упрощают обработку ограниченных иерархий классов.
sealed class Expr
data class Const(val number: Double) : Expr()
Kotlin автоматически определяет тип переменной.
val x = 10 // Int
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
2. Bundle: сохранение состояния через onSaveInstanceState() и восстановление в onCreate() или onViewStateRestored().
3. SharedPreferences: для сохранения небольших данных между запусками приложения.
4. Базы данных или файлы: для долгосрочного хранения больших объёмов данных.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥1
Java: Все объекты могут быть
null, что приводит к NullPointerException.String s = null;
int length = s.length(); // NullPointerException
Kotlin: По умолчанию переменные не могут быть null. Для допуска null используется ?.
var s: String? = null
val length = s?.length // Вернет null, если s равно null
Java: Нет различия между изменяемыми и неизменяемыми коллекциями.
List<String> list = new ArrayList<>();
list.add("a");
Kotlin: Четкое разделение на изменяемые (
MutableList) и неизменяемые (List) коллекции.val immutableList: List<String> = listOf("a", "b", "c")
val mutableList: MutableList<String> = mutableListOf("a", "b", "c")Java: Нужно вручную переопределять equals(), hashCode(), и toString().
public class User {
private String name;
private int age;
// Конструктор, геттеры, сеттеры, equals(), hashCode(), toString()
}Kotlin: Автоматическая генерация этих методов.
data class User(val name: String, val age: Int)
Java: Необходимость явного указания типов.
int x = 10;
String s = "Hello";
Kotlin: Автоматическое выведение типов.
val x = 10 // Int
val s = "Hello" // String
Java: Необходимость явного приведения после проверки instanceof.
if (obj instanceof String) {
String s = (String) obj;
System.out.println(s.length());
}Kotlin: Автоматическое приведение типа после проверки is.
if (obj is String) {
println(obj.length) // obj приводится к String
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥1
Автоматически генерируют методы equals(), hashCode(), toString(), copy().
data class User(val name: String, val age: Int)
Ограничивают иерархию классов, обеспечивая безопасность при работе с альтернативами.
sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
Создают ограниченные множества констант.
enum class Direction {
NORTH, SOUTH, EAST, WEST
}Используют object для создания единственного экземпляра.
object Database {
fun connect() { /*...*/ }
} Позволяют определять члены, доступные без экземпляра класса.
class MyClass {
companion object {
fun create(): MyClass = MyClass()
}
}Обеспечивают легковесные типы без накладных расходов на уровень объекта.
inline class Password(val value: String)
Поддерживают передачу функций как параметров и их возврат.
fun performOperation(x: Int, y: Int, operation: (Int, Int) -> Int): Int {
return operation(x, y)
} Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2👍1
Для сохранения данных за пределами фрагмента в Android можно использовать несколько методов. Основные способы включают SharedPreferences, базы данных SQLite, Room, файлы и ViewModel с ViewModelFactory.
Используется для хранения небольших порций данных в виде пар "ключ-значение". Это удобно для хранения настроек пользователя или состояния приложения.
// Сохранение данных
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("key", "value");
editor.apply();
// Чтение данных
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
String value = sharedPref.getString("key", "default_value");
Это встроенная реляционная база данных, которая позволяет хранить структурированные данные. Для работы с ней используются SQL-запросы.
// Создание базы данных
SQLiteDatabase db = getActivity().openOrCreateDatabase("MyDatabase", Context.MODE_PRIVATE, null);
db.execSQL("CREATE TABLE IF NOT EXISTS myTable (id INTEGER PRIMARY KEY, name TEXT)");
// Вставка данных
ContentValues values = new ContentValues();
values.put("name", "value");
db.insert("myTable", null, values);
// Чтение данных
Cursor cursor = db.rawQuery("SELECT * FROM myTable", null);
if (cursor.moveToFirst()) {
String name = cursor.getString(cursor.getColumnIndex("name"));
}
cursor.close();
Это библиотека, которая упрощает работу с SQLite, предоставляя абстракцию в виде аннотаций и DAO (Data Access Objects).
// Entity
@Entity
public class User {
@PrimaryKey
public int uid;
@ColumnInfo(name = "first_name")
public String firstName;
@ColumnInfo(name = "last_name")
public String lastName;
}
// DAO
@Dao
public interface UserDao {
@Insert
void insert(User user);
@Query("SELECT * FROM user")
List<User> getAll();
}
// Database
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
// Использование
AppDatabase db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "database-name").build();
UserDao userDao = db.userDao();
User user = new User();
user.uid = 1;
user.firstName = "John";
user.lastName = "Doe";
userDao.insert(user);
List<User> users = userDao.getAll();
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
•Это может случиться из-за циклических ссылок или неправильно управляемых ресурсов.
•Утечки памяти приводят к увеличению потребления памяти и ухудшению производительности приложения.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥1
ViewModel в Android гарантирует сохранение состояния до тех пор, пока соответствующее Activity или Fragment находится в памяти.
При изменении конфигурации, например, повороте экрана, Activity уничтожается и пересоздается. ViewModel выживает эти изменения конфигурации, обеспечивая сохранение состояния.
Когда вы переходите между фрагментами в одном Activity, ViewModel фрагмента сохраняет свои данные.
Если операционная система решает завершить процесс приложения для освобождения ресурсов, ViewModel будет уничтожен.
Когда пользователь закрывает Activity или приложение завершает работу (например, при нажатии кнопки "назад" до закрытия Activity), ViewModel будет уничтожен вместе с Activity.
Пример использования ViewModel с сохранением состояния при изменении конфигурации
// ViewModel
public class MyViewModel extends ViewModel {
private MutableLiveData<String> data;
public MyViewModel() {
data = new MutableLiveData<>();
}
public LiveData<String> getData() {
return data;
}
public void setData(String newData) {
data.setValue(newData);
}
}
// Activity
public class MyActivity extends AppCompatActivity {
private MyViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewModel = new ViewModelProvider(this).get(MyViewModel.class);
// Подписка на изменения данных
viewModel.getData().observe(this, newData -> {
// Обновление UI
});
// Установка новых данных
viewModel.setData("Hello, World!");
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
2. Если хэш-код совпадает, используется метод сравнения equals, чтобы отличить ключи.
3. При коллизии элементы сохраняются в одной ячейке, обычно в связанном списке или сбалансированном дереве.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥2
Для реализации приложения, которое загружает большие файлы на сервер, необходимо учитывать несколько аспектов, таких как асинхронная обработка, устойчивость к изменениям конфигурации, восстановление после неудачных попыток загрузки и отображение состояния загрузки пользователю.
В файле
build.gradle вашего модуля добавьте следующие зависимости: dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'androidx.work:work-runtime-ktx:2.7.1'
}Создайте интерфейс для API и настройте Retrofit.
// UploadAPI.java
public interface UploadAPI {
@Multipart
@POST("/upload")
Call<ResponseBody> uploadFile(@Part MultipartBody.Part file);
}
// RetrofitClient.java
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl) {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
Используйте WorkManager для загрузки файла в фоновом режиме.
// FileUploadWorker.java
public class FileUploadWorker extends Worker {
public FileUploadWorker(@NonNull Context context, @NonNull WorkerParameters params) {
super(context, params);
}
@NonNull
@Override
public Result doWork() {
String filePath = getInputData().getString("file_path");
if (filePath == null) {
return Result.failure();
}
File file = new File(filePath);
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), requestFile);
UploadAPI api = RetrofitClient.getClient("https://yourserver.com/").create(UploadAPI.class);
Call<ResponseBody> call = api.uploadFile(body);
try {
Response<ResponseBody> response = call.execute();
if (response.isSuccessful()) {
return Result.success();
} else {
return Result.retry();
}
} catch (IOException e) {
e.printStackTrace();
return Result.retry();
}
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Нет, data class не может быть наследован. Это ограничение связано с оптимизацией и специфическими функциями, такими как copy и equals, которые автоматически генерируются для data class.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥6❤1
В Android существует несколько способов запуска асинхронных операций. Наиболее распространённые из них включают использование
AsyncTask (хотя он уже устарел), HandlerThread, AsyncTaskLoader, ExecutorService и современные подходы с использованием Kotlin Coroutines и библиотеки WorkManager.AsyncTask был одним из первых инструментов для выполнения асинхронных задач, однако его использование сейчас не рекомендуется из-за проблем с управлением жизненным циклом и утечками памяти.private class MyAsyncTask extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... voids) {
// Выполнение длительной операции
return "Result";
}
@Override
protected void onPostExecute(String result) {
// Обновление UI после завершения операции
}
}
// Запуск
new MyAsyncTask().execute();HandlerThread — это удобный способ создания фонового потока с циклом обработки сообщений.HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
handler.post(new Runnable() {
@Override
public void run() {
// Выполнение длительной операции
}
});ExecutorService из стандартной библиотеки Java предоставляет более гибкий способ управления потоками.ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(new Runnable() {
@Override
public void run() {
// Выполнение длительной операции
}
});
Корутины в Kotlin — это современный и мощный инструмент для асинхронного программирования. Они упрощают работу с асинхронными задачами и обеспечивают безопасность работы с UI.
import kotlinx.coroutines.*
fun performAsyncTask() {
GlobalScope.launch(Dispatchers.IO) {
// Выполнение длительной операции
val result = longRunningTask()
withContext(Dispatchers.Main) {
// Обновление UI после завершения операции
}
}
}
suspend fun longRunningTask(): String {
delay(1000) // Симуляция длительной операции
return "Result"
}
WorkManager — это библиотека для выполнения фоновых задач, которая обеспечивает выполнение задач даже после закрытия приложения или перезагрузки устройства.public class MyWorker extends Worker {
public MyWorker(@NonNull Context context, @NonNull WorkerParameters params) {
super(context, params);
}
@NonNull
@Override
public Result doWork() {
// Выполнение длительной операции
return Result.success();
}
}
// Запуск Worker
WorkManager workManager = WorkManager.getInstance(context);
OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(MyWorker.class).build();
workManager.enqueue(request);RxJava — это библиотека для реактивного программирования, которая также может быть использована для выполнения асинхронных задач.
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.schedulers.Schedulers;
Observable.fromCallable(() -> {
// Выполнение длительной операции
return "Result";
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
// Обновление UI после завершения операции
});
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6❤1👍1
Это центральный поток, который отвечает за управление пользовательским интерфейсом приложения. Этот поток критически важен, потому что именно он обрабатывает все действия пользовательского интерфейса, включая отрисовку вьюх (views), обработку взаимодействий пользователя и выполнение анимаций. Также основной поток обрабатывает системные вызовы, такие как события жизненного цикла активности.
Все события пользовательского интерфейса, такие как нажатия кнопок, касания экрана и другие взаимодействия с пользователем, обрабатываются основным потоком. Это гарантирует, что пользовательский интерфейс отзывчив и изменения отображаются немедленно.
Основной поток исполняет задачи, связанные с пользовательским интерфейсом, такие как обновление видов или выполнение анимаций. Это означает, что любые тяжелые или длительные операции, выполненные в основном потоке, могут "зависнуть" или замедлить интерфейс, делая приложение менее отзывчивым.
Основной поток управляется циклом обработки событий, который непрерывно проверяет наличие новых действий или событий для обработки. Этот цикл, известный как Looper, извлекает события из очереди и отправляет их соответствующим компонентам для обработки.
Чтобы избежать снижения производительности интерфейса, рекомендуется не выполнять тяжелые операции, такие как сетевые запросы или обработка больших объемов данных, непосредственно в основном потоке. Вместо этого такие задачи следует выносить в фоновые потоки с помощью таких инструментов, как AsyncTask, HandlerThreads, или использовать асинхронные библиотеки и фреймворки.
// Создаем новый Handler, привязанный к Looper основного потока
Handler mainHandler = new Handler(Looper.getMainLooper());
mainHandler.post(new Runnable() {
@Override
public void run() {
// Этот код будет выполняться в основном потоке
updateUI();
}
});
public void updateUI() {
// Обновление пользовательского интерфейса
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥2❤1
Это способность программы или операционной системы выполнять несколько задач одновременно в рамках одного процесса. Эти задачи, известные как потоки, работают параллельно и могут управлять различными частями программы, что ускоряет выполнение задач и повышает эффективность использования ресурсов компьютера.
Это легковесный процесс, который может выполняться независимо. В рамках одного процесса может существовать множество потоков, каждый из которых имеет доступ к ресурсам процесса.
Позволяет достичь параллелизма (одновременное выполнение) и конкурентности (эффективное переключение между задачами в условиях ограниченных ресурсов).
Поскольку потоки делят общие ресурсы, возникает необходимость в синхронизации доступа к этим ресурсам, чтобы избежать конфликтов и ошибок, таких как "гонки за ресурсы" (race conditions). Для управления доступом используются различные механизмы синхронизации, такие как мьютексы, семафоры и мониторы.
Возникает, когда два или более потоков взаимно блокируют друг друга, ожидая освобождения ресурсов. Голодание происходит, когда один или несколько потоков не получают доступ к необходимым ресурсам в течение длительного времени.
public class MultithreadingExample {
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("Поток 1: " + i);
try {
Thread.sleep(50); // Имитация выполнения работы
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("Поток 2: " + i);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
thread1.start();
thread2.start();
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5
Выбор Android-разработки предоставляет целый ряд преимуществ, как для разработчиков, так и для бизнеса.
Является самой популярной мобильной операционной системой в мире, что обеспечивает доступ к широкой аудитории. Приложения могут достичь значительного числа пользователей по всему миру, увеличивая потенциальные рыночные возможности.
Предоставляет больше гибкости в плане настройки приложений и интеграции с операционной системой. Это открытая платформа, что позволяет экспериментировать и внедрять новшества с меньшим количеством ограничений по сравнению с другими операционными системами.
Предоставляют разработчикам мощные инструменты для создания, тестирования и отладки приложений. Kotlin, который стал основным для Android-разработки, предлагает современные возможности и улучшает производительность и читаемость кода по сравнению с Java.
Работает на множестве устройств с различными размерами экрана и характеристиками, что дает возможность охватить более широкий спектр рынка. Однако это также создает вызовы, связанные с адаптацией приложений под разные устройства.
Тесно интегрирован с Google Services, такими как Google Drive, Google Maps и другими. Это предоставляет легкий доступ к мощным инструментам и API, которые могут значительно расширить функциональность приложений.
Приложения можно распространять не только через Google Play Market. Существуют альтернативные магазины приложений и платформы, что предоставляет больше вариантов монетизации и распространения своих продуктов.
Имеет одно из самых больших сообществ разработчиков, что означает обширную поддержку, большое количество ресурсов, форумов, блогов и документации, которые могут помочь новым и опытным разработчикам.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥3