Todo android studio что это
Список дел. Устаревший способ
ToDoDatabase.java
Займёмся основной активностью. Добавим элемент меню в res/menu/main.xml с текстом Добавить. Через этот пункт мы будем переходить на вторую активность, в которой можно будет добавить новую задачу:
Добавим несколько строковых ресурсов в res/values/strings.xml:
Разметка для основной активности (список и текстовая метка, когда список пуст):
Создадим разметку для отдельного элемента списка (list_row.xml):
Создадим вторую активность EditActivity, в которой будет происходить добавление новой задачи. Разметка для этой активности
Переходим к написанию кода. Сначала код для основной активности.
Осталось написать код для второй активности:
Запускаем проект и тестируем.
Если нужно удалить задачу из списка, то вызовите контекстное меню долгим нажатием и выберите пункт Удалить.
Вы заметили, что в проекте появились зачёркнутые строчки кода у метода startManagingCursor() и конструктора SimpleCursorAdapter, которые говорят, что эти конструкции устарели.
Примечание: В своё время я изучал этот пример, который попался на каком-то сайте. Позже я обнаружил, что на самом деле существует оригинал примера на известном ресурсе. Кстати, сейчас у автора примера проект переделан под новую платформу Android 4 с использованием контент-провайдера. Позже мы дважды переделаем пример. Сначала избавимся от устаревших конструкций, а потом задействуем контент-провайдер.
Как добавить TODO и отслеживать проблемы проекта в Android Studio (НЕ в источниках)
Я пишу новую лучшую версию моего старого Android-проекта, который исправит множество ошибок пользовательского интерфейса, но также имеет лучший дизайн, необходимый для интеграции некоторых новых функций.
Когда я просматриваю исходный код, я могу видеть все свои старые и новые TODO в источнике, но есть вещи, которые я помню и забыл, что хочу делать в будущем и не вписываюсь ни в один источник.
У Eclipse был простой список задач в проекте, на котором вы могли записать и отслеживать все исправления ошибок и новые функции, которые вы хотели для этого проекта. Очень удобно!
Есть ли способ добавить такие задачи / проблемы / заметки / todos в Android Studio в проект в целом, БЕЗ добавления их в определенное место в источниках?
Чтобы добавить ToDo, просто комментируйте в любом месте своего кода, начиная со слова ToDo
Чтобы просмотреть список ToDos, посмотрите в левом нижнем углу окна Android Studio:
Если вы его откроете, вы получите это представление со списком ваших todos и опций для перехода к файлам, где они находятся в вашем проекте:
Должны быть видны в панели списка
Изменить: вы можете добавлять плагины для управления задачами в Intellij 14
Я не использовал их, так как наш рабочий процесс находится вне IDE, и я не могу прокомментировать, будут ли они работать в Android Studio.
Как и любой файл кода, вы можете запустить строку с
И IDE распознает его как одну из ваших задач. В этом файле могут быть десятки или сотни TODO. И, конечно же, вы все еще можете встроить TODO в свои файлы кода, тесно связанные с кодом, который вам нужно обновить / исправить.
Чтобы установить контрольные точки для себя в проекте студии Android, вы можете сделать это как: В Java-файле:
В XML-файле:
Кто-то выше заметил, что todo не работает внутри xml-файла, поэтому он для них.
Мой любимый способ выглядит следующим образом:
Записать (todo) после нажатия клавиши вкладок
В Android Studio в меню «Сервис» есть опция «Задачи и контексты». Вы можете вручную добавлять задачи (то есть todo, которые вы хотите выполнить для своего проекта). Это довольно просто, просто добавьте название задачи, название ветви VCS и список изменений, что может не соответствовать вашим потребностям. Следуйте по этой ссылке, чтобы узнать больше.
Урок 34. Практика. TodoApp. Список задач.
В этом уроке разбираем экран Tasks (список задач) приложения TodoApp
Прочитайте введение, чтобы понимать, как строятся уроки.
Приложение
Ниже приведен список основных экранов. По ссылке вы можете перейти в урок, в котором подробно рассматривается реализация функций экрана.
Отображается список задач. При нажатии на задачу открывается экран просмотра задачи. При нажатии на FAB кнопку открывается экран создания задачи. Есть возможность использовать фильтр по статусу задачи.
Рассматриваемые функции экрана:
1) Получение данных и отображение их в списке
2) Фильтр по типу задач
3) Удаление завершенных задач
4) Переход на экран создания новой задачи
5) Переход на экран просмотра данных задачи
6) Завершение задачи
При нажатии на FAB кнопку открывается экран редактирования задачи.
Рассматриваемые функции экрана:
1) Получение данных и отображение их на экране
2) Завершение задачи
3) Удаление задачи
4) Переход на экран редактирования задачи
При нажатии на FAB кнопку происходит возврат к списку задач
Экран
Рассмотрим экран со списком задач.
Функции экрана, которые мы будем разбирать:
Из Architecture Components здесь используются: ViewModel, LiveData и Data Binding.
Также здесь активно используется SingleLiveEvent. Это LiveData, который не будет слать последнее значение новым слушателям при их подключении. В основном это полезно при поворотах экрана, чтобы не было повторных срабатываний при переподключении слушателей. Например, чтобы повторно не показывался Toast или SnackBar, когда View после пересоздания снова подключается к LiveData.
Основные компоненты:
Схема ссылок выглядит так:
Activity и фрагмент держат ссылку на ViewModel. А ViewModel держит ссылку на репозиторий. Эта схема хороша тем, что никто не держит ссылок на Activity или фрагмент. А значит, при повороте экрана нет риска возникновения утечек.
Рассмотрим, как и где создаются основные компоненты.
TasksViewModel относится к TasksActivity. При создании TasksViewModel используется фабрика ViewModelFactory, чтобы передать TasksRepository и Application context.
Используется Application, а не Activity context, чтобы ViewModel не держала ссылку на Activity.
Фрагмент получает тот же экземпляр TasksViewModel, что и Activity. Код в TasksFragment.java:
Т.е. у Activity и фрагмента есть общий объект TasksViewModel. Это важно, потому что они будут использовать его для общения друг с другом вместо колбэков.
Взаимодействие
Рассмотрим, какие способы взаимодействия друг с другом есть у основных компонентов.
Data Binding и LiveData позволяют TasksViewModel не хранить ссылку на TasksFragment (и TasksActivity). У TasksViewModel просто нет необходимости знать что-либо о TasksFragment и просить его выполнить какое-либо действие, например, отобразить данные, прогрессбар, SnackBar и т.п. Вместо этого биндинг подписывает экранные компоненты фрагмента на Observable поля в TasksViewModel. И при изменении значений этих полей, мы автоматически видим результат на экране. Или фрагмент подписывается на LiveData, находящийся в TasksViewModel, и через него получает данные или указания.
Давайте рассмотрим это все более детально.
В layout файле фрагмента TasksFragment (tasks_frag.xml) настроен Data Binding, в котором используется TasksViewModel
Отображение списка задач
Как список с данными попадает из TasksViewModel на экран?
В TasksViewModel есть поле:
В него складываются задачи, полученные из репозитория.
При помещении в него данных, они автоматически будут отображены в списке на экране. Это реализовано биндингом. В layout файле в ListView используется viewmodel.items:
У ListView, конечно, нет атрибута items. Он создан искусственно с помощью BindingAdapter.
Из ListView достается адаптер и ему передаются данные items.
Нет данных
Как TasksViewModel показывает другое содержимое экрана в случае, если данных нет?
В TasksViewModel есть поле:
Этот boolean флаг определяет, что будет отображаться на экране: список с данными или тексты/иконки о том, что данных нет.
Реализовано это биндингом для атрибута visibility в нескольких View
Отображение процесса загрузки данных
Как отображается прогрессбар при загрузке данных?
В TasksViewModel есть поле:
Этот boolean флаг, отвечает за отображение прогрессбара во время загрузки данных.
Реализовано это биндингом. В layout этот флаг используется в ScrollChildSwipeRefreshLayout
Атрибута refreshing у ScrollChildSwipeRefreshLayout нет. Но и BindingAdapter здесь не используется. Тут сделано хитро. Когда мы передаем значение в какой-либо атрибут View, биндинг пытается в классе View найти метод set* для этого атрибута. В данном случае, биндинг будет пытаться вызвать метод setRefreshing в классе ScrollChildSwipeRefreshLayout. Такой метод есть, он включает/выключает крутилку (прогрессбар). И мы передаем туда boolean из viewmodel.dataLoading.
Отображение ошибки при загрузке данных
Как TasksViewModel показывает другое содержимое экрана в случае, если была ошибка при загрузке данных?
В TasksViewModel есть поле:
Но я не нашел, как оно используется. Похоже, это просто забыли реализовать, потому что в layout файле тоже нет никаких View, которые могли бы быть показаны в случае ошибок. Но в целом логика должна быть примерно та же, что и в случае отсутствия данных.
Обновление списка при pullToRefresh
Как TasksViewModel узнает о том, что был pullToRefresh?
В layout у ScrollChildSwipeRefreshLayout в параметр onRefresh передается viewmodel:
И тут снова используется BindingAdapter.
Для ScrollChildSwipeRefreshLayout вешается обработчик OnRefreshListener, в котором просим viewModel снова загрузить данные.
Отображение SnackBar
Как TasksViewModel отображает SnackBar?
В TasksViewModel есть поле:
В нашем случае подписчиком будет фрагмент. В onActivityCreated класса TasksFragment.java выполняется подписка:
Подписываемся и при получении ID строки отображаем SnackBar.
onActivityResult
Как TasksViewModel обрабатывает результаты вызовов startActivityForResult?
Из Activity будут идти вызовы startActivityForResult. Обработка результатов этих вызовов будет делегирована TasksViewModel.
Адаптер списка
Как TasksViewModel получает нажатия на элементы списка?
Давайте отдельным пунктом рассмотрим адаптер, т.к. в нем реализованы обработчики нажатий на элементы списка.
TasksViewModel передается в конструктор адаптера TasksAdapter.java:
Далее она будет использована при обработке нажатий.
В методе getView в TasksAdapter.java настраивается биндинг:
Сначала методом DataBindingUtil.inflate создается пара view + биндинг в случае, когда view == null. Если же view пришло не null, то получаем из него биндинг.
Далее создается слушатель, методы которого будут использоваться биндингом в layout. Чуть дальше увидим, где именно.
Слушатель и задача передаются в биндинг. И процесс биндинга запускается безотлагательно.
Метод binding.getRoot() вернет корневое View биндинга.
В layout файле task_item.xml прописаны вызовы обоих методов слушателя.
На onClick корневого LinearLayout висит метод onTaskClicked
А на onClick чекбокса висит onCompleteChanged
Соответственно, при нажатии на задачу в списке и при нажатии на чекбокс будут вызваны методы слушателя, которые в свою очередь вызовут методы TasksViewModel.
Функции
1) Получение данных и отображение их в списке
Схема выглядит так:
1. Начинается все в фрагменте, в методе onResume.
Метод start приводит к вызову метода loadTasks в TasksViewModel.java. В этом методе происходит следующее:
2. Включается отображение прогрессбара
3. Запускается процесс получения данных из репозитория
Ответ получим в колбэк.
Далее могут быть два варианта: приходят данные или ошибка. Соответственно, в моем тексте будет два продолжения цепочки шагов с пункта 4.
Сначала рассмотрим вариант с данными.
В зависимости от установленного на экране фильтра, из полученных из репозитория задач формируется список tasksToShow.
5. Выключается прогрессбар.
6. Выключается отображение ошибки в UI (она могла быть включена во время предыдущей попытки получения данных)
7. Задачи из отфильтрованного списка tasksToShow передаются в items
Биндинг отобразит их на экране.
8. Устанавливается флаг empty в зависимости от того, есть ли данные в items.
Биндинг в зависимости от значения empty отобразит либо список, либо тексты/картинки показывающие пользователю, что данных нет.
Теперь рассмотрим вариант, когда репозиторий вернул ошибку.
Схема почти та же:
5. Включается отображение ошибки UI.
Как я уже написал при разборе биндинга, этот флаг почему-то никак не используется. Но он мог бы отображать какой-то текст на экране.
2) Фильтр по типу задач
Мы можем выбрать, какой тип задач будет отображаться в списке: все, незавершенные или завершенные.
В фрагменте по нажатию на меню фильтра вызывается popup menu. И для него вешается обработчик.
Метод showFilteringPopUpMenu в TasksFragment.java:
При нажатии на пункт меню происходит следующее:
1. В зависимости от нажатого пункта popup меню, выбранный тип фильтра передается в TasksViewModel в метод setFiltering.
Метод setFiltering в TasksViewModel.java выглядит так:
Фильтр сохраняется в поле mCurrentFiltering. А под троеточиями скрыт код настройки текстов/картинок в зависимости от фильтра.
2. Вызывается метод loadTasks, который мы рассмотрели в предыдущей функции. Он сработает по той же схеме. Просто перед запуском loadTasks будет установлен фильтр mCurrentFiltering. И когда данные придут из репозитория, TasksViewModel просеет их с учетом mCurrentFiltering, и на экран попадут только нужные задачи.
3) Удаление завершенных задач
Мы можем удалять завершенные задачи из списка.
При нажатии на этот пункт меню в TasksFragment.java вызывается метод:
Содержимое метода clearCompletedTasks в TasksViewModel.java:
1.Вызов метода репозитория для удаления выполненных задач
2. Отображение SnackBar
3. Загрузка свежих данных.
4) Переход на экран создания новой задачи
Схема вызова другого Activity и получения от него результата:
1. В фрагменте по нажатию на кнопку добавления вызывается метод:
2. Содержимое метода addNewTask в TasksViewModel.java:
TasksActivity подписалось на этот SingleLiveEvent еще при создании, в своем onCreate методе:
В основе SingleLiveEvent лежит LiveData. Мы используем Activity (this), как Lifecycle при подписке, следовательно, подписка будет учитывать состояние Activity. И когда Activity будет уничтожено, например, при повороте экрана, Observer будет отписан автоматически и никаких утечек памяти не будет.
Идет вызов Activity для создания новой задачи и ожидание ответа (т.к. startActivityForResult, а не startActivity).
4. При сохранении, в AddEditTaskActivity будет вызван код:
5. Напомню, что в TasksActivity в методе onActivityResult идет вызов TasksViewModel.handleActivityResult.
6. Когда экран создания новой задачи вернет положительный результат, будет показан SnackBar.
А данные в списке обновятся, т.к. в onResume фрагмента идет вызов метода mTasksViewModel.start().
5) Переход на экран просмотра данных задачи
Схема очень похожа на предыдущую и шаги примерно те же.
1-2. При нажатии на задачу в списке, адаптер выполнит код:
Метод getOpenTaskEvent в TasksViewModel.java возвращает mOpenTaskEvent
TasksActivity подписалось на этот SingleLiveEvent еще при создании, в своем onCreate методе:
3. Метод openTaskDetails в TasksActivity.java:
Идет вызов TaskDetailActivity для просмотра данных задачи. И ему передается ID задачи.
4-6. Результат будет обработан в TasksViewModel. Если он положительный, то будет показан SnackBar
6) Завершение задачи
По нажатию на чекбокс, задача должна сменить статус на Завершена.
1. При нажатии на чекбокс задачи в списке, адаптер выполнит код:
Содержимое метода completeTask в TasksViewModel.java:
2. Идет вызов соответствующего метода репозитория
Т.е. мы ставим чекбокс, но при этом не меняем статус задачи в адаптере. И после скролла задача не отобразит свой актуальный статус, потому что она просто не знает его. Также по этой причине не меняется фон задачи. Он сразу должен быть серым, если задача завершена.
Тут надо либо вручную менять статус задачи в адаптере и вызвать notifyItemChanged, либо запрос новых данных делать.
Возможно, это еще пофиксят.
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Как написать простое Android ToDo-приложение на Java
Предисловие
Я не являюсь профессиональным разработчиком с огромным стажем в данной области (и это даже не хобби, а лишь нужда в разработке конкретного приложения), потому данная статья, полагаю, будет полезна новичкам, таким же, как и я был в начале разработке своего приложения. Возможно, кто-то найдет что-то полезное из данной статьи, какие-то кусочки окажутся частью ваших будущих разработок.
Я расскажу вам как написать простенькое ToDo-приложение на Android с тремя активностями (рабочими экранами).
Ссылка на проект на Github будет в конце данной статьи.
Установка и первичная настройка
После успешной установки IDE и запуска нажимаем на самую первую кнопку Start a new Android Studio Project. Далее появится мастер первичной подготовки проекта:
На следующем экране придумываем имя приложению; помните, что package name, после публикации на Google Play изменить нельзя (иначе Google Play посчитает это другим приложением (поправьте меня, если я ошибаюсь). Выбираем язык Java, так как по нему данная статья, а также, по нему больше информации в Интернете, чем по Kotlin.
Минимальный SDK выбираем под Android 5.0, так как данного API будет предостаточно для наших задач, заодно мы получим большой охват, в том числе старых устройств: планшеты, смартфоны, встроенные системы.
Скриншоты: установка и первичная настройка
Советую вам размещать объекты под ConstraintLayout, так объекты можно будет привязывать узелками к родительскому ConstraintLayout, который по умолчанию занимает всю пространство, а после привязки узелков, мы можем размещать объекты на нужном нам вертикальном и горизонтальном выравнивании.
Создание String-переменной
Для перевода интерфейса, необходимо сохранить изменения и над нашим конструктором Layout нажать на кнопку Default (en-us) и выбрать Edit Translations, далее найти слева сверху значок глобуса и нажать на него для добавления нового языка:
Переводы для интерфейсов
Таким образом создадим дополнительные макеты (layouts) для оставшихся двух окон:
Скриншоты: еще два макета
Программируем на Java под Android
Еще раз повторюсь, что это Tutorial больше для новичков; дальше я буду комментировать практически каждую строчку. Ссылка на проект на Github будет в конце данной статьи.
Открываем файл Main_Activity.java, который будет отвечать за логику наших переключателей и главного экрана в целом, а она такова:
В самом верху должен отображаться пользовательский заголовок, если он настроен.
На переключателях должен отображаться тот текст, который пользователь настраивает из окна с макетом Activity_Settings.xml
Количество переключателей должно соответствовать заданному числу из окна макета Activity_Advanced.xml
После выхода из приложения и повторного запуска все переключатели должны оставаться в том же положении, в котором пользователь их оставил
Сброс переключателей возможен только, если переключатель Уверен/-а? включен.
А также, должны работать оставшиеся кнопки меню.
Код под спойлером: 156 строчек
Следующим этапом будет написание кода для корректной работы макета Activity_Settings.XML, а логика его такова:
Введенные пользователь записи сохраняются даже после перезапуска приложения
Количество полей соответствуют числу, заданному в настройках из макета Activity_Advanced.xml
А также, должны работать оставшиеся кнопки меню.
Код по спойлером: 124 строчки
Текстовый заголовок, который пользователь может ввести и который будет отображаться на главной странице/активности.
Также, текстовый заголовок и выбранное количество полей с помощью радиокнопок должны сохранять свое состояние даже после перезапуска приложения.
И наконец должны работать оставшиеся кнопки меню.
Код под спойлером: 134 строчки
Подготовка приложения к публикации
Для отладки и проверки работоспособности приложения советую вам использовать настоящее устройство на Android, так вы сразу сможете отследить наличие, как минимум проблем с оформлением.
Здесь я приложил видео-инструкцию, как подключить свой смартфон к Android studio для отладки вашего приложения. На видео вы можете заметить первую версию данного приложения с очень плохим кодом:
Регистрация в Google Play
Для публикации приложения нам следует создать специальный аккаунт разработчика, вот прямая ссылка.
После оплаты и успешной авторизации в консоли разработчика, необходимо нажать на синюю кнопку «Создать приложение«, далее заполнить все необходимые поля:
После создания приложения в консоли разработчика Google Play, необходимо перейти в раздел Рабочая версия и нажать на кнопку Создать новый выпуск. Вам предложат получить электронную подпись для вашего приложения с расширением *.jks, с помощью которой вам предстоит подписать свое первое приложение, а также, все дальнейшие выпуски с обновлениями.
Наконец, переходим в следующий раздел: пункт меню Build>Generate Signed Bundle / APK
В открывшимся окне выбираем APK. В подразделе Key Store Path выбираем Create new, далее заполняем все поля (прямая ссылка на официальную инструкцию), далее данный ключ потребуется загрузить в консоль Google Play. Затем вернемся в Android Studio и после ввода всех необходимых данных, нажимаем Next
После загрузки файла приложения APK потребуется заполнить множество форм и подготовить множество материалов: описание на разных языках (если необходимо), изображения на разных языках (надписи на изображениях я имею в виду), логотипы, иконки разных размеров, скриншоты со смартфона и планшета.
Наконец отправляем приложение в публикацию. Сотрудники Google Play будут проверять ваше приложение в течении 2 недель, судя по официальным данным. Данное приложение рассматривали в течении 5 суток. Также, стоит учесть, что каждое обновление, также, будут проверять, но на обновления уходит не более 2-3 суток.
Ссылка на GitHub, как обещано. Ссылка на приложение в Google Play.