Как устроен экран приложения: Activity и View на Java

Activity — это экран (контроллер UI) и контейнер для иерархии View; View/ViewGroup — видимые элементы и макеты, которые Activity отображает и с которыми взаимодействует пользователь.

Что такое Activity и её жизненный цикл

Activity представляет один экран приложения и управляет состояниями интерфейса: создание, видимость, пауза и уничтожение. Ключевые методы жизненного цикла:

  • onCreate(Bundle) — инициализация, установка layout через setContentView().
  • onStart(), onResume() — Activity видима и готова к взаимодействию.
  • onPause(), onStop() — нужно сохранять состояние и освобождать ресурсы.
  • onDestroy() — финальная очистка.

Пример базовой Activity на Java:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main); // подключаем XML-макет

        Button button = findViewById(R.id.myButton);
        button.setOnClickListener(v -> 
            Toast.makeText(this, "Кнопка нажата!", Toast.LENGTH_SHORT).show()
        );
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // очистка слушателей при необходимости
    }
}

Советы:

  • Сохраняйте состояние (onSaveInstanceState) при смене конфигурации.
  • Переносите тяжёлую работу в фон (Executor, WorkManager).

View, ViewGroup и макеты (XML и программно)

View — базовый элемент: TextView, Button, ImageView. ViewGroup — контейнер для других View. Популярные макеты:

  • ConstraintLayout — гибкий, уменьшает вложенность.
  • LinearLayout — упорядочивает по оси, удобен для простых форм.
  • FrameLayout — накладывает слои (контейнер для фрагментов). Используйте ViewBinding для типобезопасного доступа к элементам вместо ручного findViewById.

Пример XML с ConstraintLayout:

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"/>

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/title"/>
</androidx.constraintlayout.widget.ConstraintLayout>

События, RecyclerView и фрагменты

Обработка кликов и жестов через OnClickListener, OnTouchListener или GestureDetector. Для длинных списков используйте RecyclerView с Adapter и ViewHolder:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
    private final List<String> items;
    public static class MyViewHolder extends RecyclerView.ViewHolder {
        TextView textView;
        MyViewHolder(View v) { super(v); textView = v.findViewById(R.id.text); }
    }
    @Override public void onBindViewHolder(MyViewHolder holder, int pos) {
        holder.textView.setText(items.get(pos));
        holder.itemView.setOnClickListener(v -> handleClick(pos));
    }
    // остальные обязательные методы...
}

Фрагменты дают модульность внутри Activity, управляются FragmentManager и позволяют переиспользовать UI (телефон/планшет).

Используйте ViewBinding для безопасности типов и избегайте многократных вызовов findViewById.

Не выполняйте тяжёлые операции в UI-потоке — приложение будет "замерзать".

Частые ошибки

  • Привязки в onCreate без проверки null после смены конфигурации — при пересоздании Activity элементы могут быть недоступны.
  • Утечки: удержание ссылок на Context или Views в статических полях, не снятые слушатели.
  • Сложные вложенные макеты — снижает производительность; заменяйте на ConstraintLayout.
  • Блокировка главного потока при загрузке изображений или запросах сети — используйте Glide, Coil, Coroutines/Executor.

FAQ

  • Нужно ли всегда использовать Fragment? Нет — фрагменты полезны для переиспользования UI и адаптивности, но простые экраны можно реализовать напрямую в Activity.
  • Когда переходить на Jetpack Compose? Compose упрощает декларативный UI; переход имеет смысл при новых экранах и поддержке команды, но существующий код на View/ViewGroup остаётся рабочим.
  • Как избежать утечек памяти с слушателями? Снимайте слушатели в onDestroy/onStop и не храните Activity в статических полях.

Начните с простого проекта: создайте Activity, добавьте несколько View в ConstraintLayout, подключите RecyclerView — и постепенно заменяйте устаревшие подходы на ViewBinding и архитектурные паттерны (MVVM).