Похожие презентации:
Технология разработки мобильных приложений
1.
ТЕХНОЛОГИЯ РАЗРАБОТКИМОБИЛЬНЫХ
ПРИЛОЖЕНИЙ
2.
ЧТО ВАМ ПОНАДОБИТСЯ ДЛЯ ИЗУЧЕНИЯ КУРСА?Знание любого объектно-ориентированного языка
Знание английского языка
Среда разработки Android Studio
http://developer.android.com/studio/#Requirements
Физическое устройство с ОС Android
3.
ПОЧЕМУ ANDROID?Наиболее популярная система в наше время
Огромный выбор смартфонов от 50$ (iOS от 299$)
Система с открытым исходным кодом
25$ за аккаунт разработчика (iOS – 99$ каждый год)
Катализатор экономического роста
4.
ANDROID: ТОГДА И СЕЙЧАСПервый смартфон T-Mobile G1 (2008 год)
Планшеты, часы, телевизоры…
Разработка под Android
Java
2008 – Java 6
2013 – Java 7
2017 – Java 8
5.
РАЗРАБОТКА ПОД ANDROIDJava
Kotlin
до 2017 – поддержка с помощью плагинов
2017 – поддержка в Android Studio 3.0 из
коробки
Библиотеки поддержки
com.android.support:appcompat-v7:27.0.1
com.android.support:design:27.0.1
com.android.support: support-v13:27.0.1
и другие
Библиотеки добавляются в файл gradle уровня app.
6.
ВНУТРЕННЯЯ АРХИТЕКТУРА ANDROIDДом
Приложения
Контакты
Телефон
Браузер
…
Платформа приложений
Диспетчер ресурсов
…
…
…
Библиотеки
Выполняемая среда
…
OpenGL|ES
SGL
Драйвер
дисплея
…
FreeType
SSL
SQLite
WebKit
libc
Драйвер
камеры
Ядро Linux
Драйвер
Bluetooth
Основные библиотеки
Виртуальная машина
…
…
…
…
7.
УСТАНОВКА ПРОГРАММНОГО ОБЕСПЕЧЕНИЯУстановка инструмента Java SE Development Kit 8
Установка интегрированной среды разработки Android Studio
Установка виртуального эмулятора/подключение
физического устройства
8.
ИНТЕРФЕЙС ANDROID STUDIO9.
ИНТЕРФЕЙС ANDROID STUDIO. СТРУКТУРА ПАПОК ПРОЕКТА10.
СТРУКТУРА ПАПОК ПРОЕКТА11.
СОДЕРЖИМОЕ ФАЙЛА BUILD.GRADLE УРОВНЯ APP12.
СОДЕРЖИМОЕ ФАЙЛА MAINACTIVITY.JAVA13.
МАКЕТЫ ДИЗАЙНА14.
МАКЕТЫ ДИЗАЙНА15.
РЕДАКТОР МАКЕТА16.
НАДПИСЬ (TEXTVIEW)Изменение размера:
android:textSize="14sp"
Определение в XML
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/text" />
Использование надписи в коде активности
TextView tV = (TextView)
findViewById(R.id.textview);
textView.setText("Some other string");
17.
ТЕКСТОВОЕ ПОЛЕ (EDITTEXT)Определение в XML
<EditText
android:id="@+id/edit_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/edit_text" />
Атрибут android:inputType="number"
phone - предоставляет клавиатуру для ввода номеров.
textPassword - для ввода пароля.
textCapSentences - первое слово с прописной буквы.
textAutoCorrect - исправляет вводимый текст.
Использование в коде активности
EditText editText = (EditText)
findViewById(R.id.edit_text); String text =
18.
КНОПКА (BUTTON)Определение в XML
<Button android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_text" />
Использование в коде активности
android:onClick="onButtonClicked"
Затем в активности определяется метод следующего
вида:
/** Вызывается при щелчке на кнопке */
public void onButtonClicked(View view) {
// Сделать что-то по щелчку на кнопке
19.
ЭЛЕМЕНТЫ УПРАВЛЕНИЯ20.
ПЕРЕКЛЮЧАТЕЛИ (RADIOBUTTON)Определение в XML
<RadioGroup android:id="@+id/radio_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton android:id="@+id/radio_circle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/circle" />
<RadioButton android:id="@+id/radio_square"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/square" />
</RadioGroup>
21.
ЭЛЕМЕНТЫ УПРАВЛЕНИЯраскрывающийся список (Spinner)
графическое представление (ImageView)
графическая кнопка (ImageButton)
прокручиваемые представления (ScrollView)
уведомления (Toast)
Toast.LENGTH_LONG=3,5 с
Toast.LENGTH_SHORT=2 с
22.
ANDROID MANIFEST23.
СТРУКТУРА МАНИФЕСТАтег <application>
тег <activity>
тег <service>
тег <receiver>
тег <provider>
permissions
<uses-permission>
24.
INTENTЗапустить другое приложение
Открыть файл
Перейти на другой экран
Бывают: явные (explicit) и неявные (implicit)
Activity 1
Intent
Activity 2
Activity 3
25.
ИНТЕНТЫ ОБЫЧНО СОДЕРЖАТИмя компонента
Действие – action (ACTION_VIEW, ACTION_SEND и др.)
Категория – category
Данные – data
Дополнительные параметры
26.
ДЕЙСТВИЯ И КАТЕГОРИИ ИНТЕНТАДействия:
ACTION_SEND
ACTION_DIAL
• ACTION_EDIT
Категории – category (CATEGORY_LAUNCHER,
CATEGORY_BROWSABLE)
Данные – data (URI)
27.
ДАННЫЕ И ДОПОЛНИТЕЛЬНЫЕ ПАРАМЕТРЫ ИНТЕНТАДанные – data (URI)
Дополнительные параметры – extras*
*Например, при создании объекта Intent для отправки
сообщения электронной почты с методом ACTION_SEND можно
указать получателя с помощью ключа EXTRA_EMAIL, а тему
сообщения - с помощью ключа EXTRA_SUBJECT.
28.
INTENT FILTERactivity
service
29.
ОПРЕДЕЛЕНИЕ РАЗМЕРОВРазмер экрана (small, normal, large, extra-large)
Плотность экрана (dpi – dots per inch): ldpi, mdpi
(~160dpi), hdpi, xhdpi, xxhdpi, xxxhdpi
Разрешение экрана
dp = длина в пикселях * 160 / плотность экрана
px = dp * плотность экрана / 160
px – пиксели
in – inch, дюйм – примерно 2,54 см
pt – point, точка – 1/72 дюйма
sp – пиксели, не зависящие от масштаба, применяются
при указании размеров шрифтов текста
30.
ОСНОВНЫЕ КОМПОНЕНТЫ ANDROID-ПРИЛОЖЕНИЯApplication
Activity
Service
BroadcastReceiver
ContentProvider
31.
ОСНОВНЫЕ КОМПОНЕНТЫ ANDROID<activity android:name=“.MainActivity”></activity>
<service android:name=“.CustomService”/>
public class CustomReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: start service
}
}
ContentProvider
32.
CONTEXTДоступ к ресурсам
Доступ к системным возможностям устройства
Динамическое изменение интерфейса
Создание файлов
33.
ЖИЗНЕННЫЙ ЦИКЛ ПРИЛОЖЕНИЯЖизненный цикл приложения в Android жёстко
контролируется системой и зависит от нужд пользователя,
доступных ресурсов
Android всегда уничтожает активити, а не компоненты
34.
ПРИОРИТЕТЫ ПРОЦЕССОВ В ANDROIDПроцессы
переднего
плана
Видимые
процессы
Служебные процессы
Фоновые процессы
Пустые процессы
35.
ОСНОВНЫЕ МЕТОДЫ ЖИЗНЕННОГО ЦИКЛАResumed
(visible)
onResume()
onStart()
Create
d
onCreate()
Started
(visible)
onResume()
onStart()
onRestart()
onPause()
Paused
(partly visible)
onStop()
Stopped
(hidden)
onDestroy()
Destroye
d
36.
ONRESUME() И ONPAUSE()Метод onResume() вызывается после onStart(). Также может
вызываться после onPause().
onPause():
сохраняет незафиксированные данные
деактивирует и выпускает монопольные ресурсы
останавливает воспроизведение видео, аудио и анимацию
37.
ONSTOP() И ONRESTART()Метод onStop() вызывается, когда окно становится невидимым
для пользователя. Всегда сопровождает любой вызов метода
onRestart().
Если окно возвращается в приоритетный режим после вызова
onStop(), то в этом случае вызывается метод onRestart(). Всегда
сопровождает любой вызов метода onStart().
38.
ПОРЯДОК ВЫЗОВА МЕТОДОВ ЖИЗНЕННОГО ЦИКЛА ПРИЗАПУСКЕ ДОЧЕРНЕЙ ACTIVITY
ACTIVITY 1
onCreate()
onStart()
onResume()
*Запуск второй активити*
onPause()
ACTIVITY 2
onCreate()
onStart()
onResume()
onStop()
*возврат назад*
onPause()
onRestart()
onStart()
39.
УНИЧТОЖЕНИЕ АКТИВИТИСистема считает за нормальное поведение:
нажатие кнопки “назад”
вызов метода finish()
Система сохраняет стейт при следующих случаях:
изменении конфигурации (поворот экрана, смена языка,
доступность клавиатуры)
уничтожение фоновой Activity при нехватке памяти для рабочей
Activity
40.
КЛАССИФИКАЦИЯ АКТИВИТИАктивити верхнего уровня
Активити категорий
Активити детализации/редактирования
41.
ИНТЕРФЕЙС. VIEW И VIEWGROUP<ViewGroup>
//Иерархическая структура
разметки, XML правила
<View/>
<View/>
<ViewGroup>
<View/>
<View/>
</ViewGroup>
</ViewGroup>
42.
LINEARLAYOUTКорневой LinearLayout
(фиолетовый):
android:orientation=“vertical”
Вложенный LinearLayout
(малиновый):
android:orientation=“horizontal”
android:weightSum=“4”
Кнопки горизонтального LinearLayout:
android:layout_weight=“1” / ”2”
android:layout_width=“0dp”
43.
РЕАЛИЗАЦИИ VIEWGROUPLinearLayout
RelativeLayout
FrameLayout
ConstraintLayout
44.
РАЗМЕР VIEW-ЭЛЕМЕНТОВАтрибуты:
layout_height – высота
layout_width – ширина
layout_weight (LinearLayout) – вес
weight_sum (LinearLayout)
Значения высоты и ширины:
конкретные значения (40dp)
wrap_content – по содержимому
match_parent – до краёв родителя
45.
РАСПОЛОЖЕНИЕ VIEW-ЭЛЕМЕНТОВАтрибуты:
layout_margin – внешний отступ
padding – внутренний отступ
gravity – притяжение элементов внутри текущего элемента
layout_gravity – притяжение элементов относительно
родительского
46.
РАБОТА С РЕСУРСАМИ ПРИЛОЖЕНИЯ@android:drawable/ic_search_category_default – ссылка на иконку
поиска
android:text="@string/example_text" – задаём текст из строкового
ресурса в xml
mTextView.setText(R.string.app_name); – задаём текст из строкового
ресурса в коде
android:src="@android:drawable/ic_delete" – устанавливаем png
drawable с помощью атрибута src у ImageView
47.
ACTIVITY BACKSTACKСтарт
Активити 2
Старт
Активити 3
Активити переднего плана
Активити
Активити
1
2
Активити
1
Back Stack
Back Stack
Активити
3
Активити
2
Активити
1
Back Stack
Переход назад (back)
Активити
3
Activity 3
destroyed
Активити
2
Активити
1
Back Stack
48.
LAUNCHMODEЗначения:
standard (по умолчанию)
singleTop
singleTask
singleInstance
49.
INTENTFLAGS. TASKAFFINITYФлаги:
FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_SINGLE_TOP
FLAG_ACTIVITY_CLEAR_TOP
50.
НАЗНАЧЕНИЕ АДАПТЕРАДанные:
Финляндия
Швеция
Эстония
(массив строк)
Адаптер
создаёт View
для
отображения
данных
Финляндия
Швеция
Эстония
51.
СПИСОК ГОТОВЫХ АДАПТЕРОВArrayAdapter<T>
CursorAdapter
SimpleAdapter
ResourceCursorAdapter
SimpleCursorAdapter
// набор данных, которые свяжем со списком
final String[] balticContries = new String[] { “Finland”, “Sweden”,
“Estonia” };
ListViewbalticContries = (ListView) findViewById(R.id.listView);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
R.layout.list_item, balticContries)*;
listView.setAdapter(adapter);
52.
ARRAYADAPTER. ОПРЕДЕЛЕНИЕ LISTVIEW В XMLArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
R.layout.list_item, balticContries)*;
<ListView
android:id=“@+id/list_options”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:entries=“@array/options” />
<string-array name=“options”>
<item>Sport</item>
<item>Contact</item>
<item>Stores</item>
</string-array>
53.
ОБРАБОТКА ЩЕЛЧКОВ LISTVIEWAdapterView.OnItemClickListener
itemClickListerner = new
AdapterView.OnItemClickListener(){
public void
onItemClick(AdapterView<?> listView, View
itemView, int position, long id) {
if (position == 0) {
Intent = new
Intent(MainActivity.this,
TargetActivity.class);
startActivity(intent);
}
}
54.
RECYCLERVIEW55.
КОМПОНЕНТЫ RECYCLERVIEWLayoutManager – размещает элементы
ItemAnimator – анимирует элементы
Adapter – создаёт элементы
ItemDecoration – дорисовывает элементы
ViewHolder – кэширует findViewById
56.
ОСНОВНОЕ API ADAPTERpublic ViewHolder onCreateViewHolder(ViewGroup parent, int
viewType)
public void onBindViewHolder(ViewHolder holder, int position)
public int getItemCount()
57.
ФРАГМЕНТФрагмент зависит от активити
Должен быть встроен в активити
Фрагмент не обязан быть частью макета активити
58.
ФРАГМЕНТЫ. ФИЛОСОФИЯ ПРОЕКТИРОВАНИЯПоявились в Android версии 3.0 (API уровня 11)
Динамичность и гибкость пользовательских
интерфейсов
Повторное использование фрагментов
59.
СОЗДАНИЕ ФРАГМЕНТАИЛИ
Активити A
Активити B
Активити A с двумя
фрагментами
60.
СОЗДАНИЕ ФРАГМЕНТАДля создания фрагмента необходимо создать подкласс класса
Fragment.
Класс Fragment имеет код, во многом схожий с кодом Activity. Он
содержит методы обратного вызова, аналогичные методам
операции, такие как:
onCreate(), onStart(), onPause() и onStop()
onCreate()
onCreateView()
onPause()
Подкласс DialogFragment
61.
РЯД ПОДКЛАССОВDialogFragment
ListFragment
PreferenceFragment
public View onCreateView()
62.
ДОБАВЛЕНИЕ ПОЛЬЗОВАТЕЛЬСКОГО ИНТЕРФЕЙСАpublic class CameraFragment extends Fragment {
public CameraFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup
container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_camera,
container, false);
}
}
63.
ДОБАВЛЕНИЕ ФРАГМЕНТА В АКТИВИТИОбъявить фрагмент в файле макета активити
Или программным способом, добавив фрагмент в
существующий объект ViewGroup
64.
SHAREDPREFERENCESМетоды получения объекта SharedPreferences:
getSharedPreferences()
getPreferences()
PreferenceManager.getDefaultSharedPreferences()
Константа доступа: Context.MODE_PRIVATE
65.
ФОРМАТ JSON{
“name”:”Тонких Артём Петрович”,
“age”:42,
“kids”:[
{
“name”:”Тонких Артём Артёмович”,
“age”:8,
“kids”:null
}
]
}
66.
ПРОЦЕССЫ И ПОТОКИПроцесс – глобальная сущность, выделенные ресурсы
Поток – внутренняя сущность процесса, выполняет
программный код
67.
ПРОБЛЕМЫ МНОГОПОТОЧНОСТИ68.
МНОГОПОТОЧНОСТЬ В ANDROIDПользователь
нажал на кнопку
Запрос
передаётся
в фоновый
поток
Запуск
фонового
потока
Показ
результата
Загрузка
Сетевой
запрос
BG
Thread
Результат
передаётся
в главный
поток
Завершение
фонового
потока
UI
Thread
69.
THREAD И RUNNABLEpublic class MyThread extends
Thread{
@Override
public void run() {
//do something
}
}
new Thread (new Runnable() {
@Override
public void run() {
//do something
}
});
new MyThread().start();
70.
SYNCHRONIZED. WAIT/NOTIFYThread 2
Thread 1
1
3
synchronized
2
if (condition()){
wait()
}
4
5
notify()
6
71.
NOTIFYALL. VOLATILEПоток 2
Поток 1
1
3
synchronized
2
if (condition()){
wait()
}
4
5
7
notify()
6
72.
EXECUTORSERVICE. CALLABLE. FUTUREExecutorService executorService =
Executors.newFixedThreadPool(4);
Future<String> future = executorService.submit(new
Callable<String>() {
@Override
public String call() throws Exception {
//do something
return result;
}
});
while (!future.isDone()) {
TimeUnit.MILLISECONDS.sleep(100);
}
String result = future.get();
73.
ИНСТРУМЕНТЫ ДЛЯ ОБЕСПЕЧЕНИЯ МНОГОПОТОЧНОСТИService + BroadcastReceiver
AsyncTask
HandlerThread / HaMeR
Loaders
74.
ВИДЫ SERVICEService – это компонент приложения, который
используется для выполнения долгих операций в
бэкграунде, без взаимодействия с пользовательским
интерфейсом.
Foreground – заметно для пользователя
Background – незаметно для пользователя
Bound – взаимодействие через интерфейс
75.
СОЗДАНИЕ SERVICEpublic class MyService extends Service {
public CustomService() {
}
@Override
@Nullable
public Ibinder onBind(Intent intent) {
return null;
}
}
76.
ЖИЗНЕННЫЙ ЦИКЛ SERVICECall to bindService()
Call to startService()
onCreate()
onStartCommand()
Active
LifeTime
onCreate()
onBind()
Service running
Clients are bound to service
The service is stopped
by itself or a client
All clients unbind by
calling unbindService()
onUnbind()
onDestroy()
onDestroy()
Service shut down
Service shut down
Bounded service
Unbounded service
77.
СОЗДАНИЕ BROADCASTRECEIVER•Добавляем новый класс, отнаследованный от
BroadcastReceiver
•Переопределяем метод onReceive()
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//TODO: do something
}
}
78.
ОТПРАВКА СООБЩЕНИЙМы можем использовать BroadcastReceiver, чтобы передавать
свои собственные сообщения.
Intent intent = new Intent();
intent.setAction (“ru.rosdistant.edu.SOMETHING_JUST_HAPPEN”);
intent.putExtra (“ARG_DATA”, “SOME_VALUE”);
sendBroadcast(intent);
79.
ИНТЕРФЕЙС ASYNCTASKmSampleTask.execute(10L) // запуск задачи
mSampleTask.cancel(true) // отмена задачи
class SampleTask extends AsyncTask<Long, Integer, String> {
void onPreExecute(); // UI-поток перед фоновой операцией
String doInBackground(Long… longs); // фоновый поток
void onPostExecute(String s); // UI-поток после фоновой операции
void publishProgress(1,2,3,4); // внутри фоновой операции
void onProgressUpdate(Integer… values); // в UI-потоке
boolean isCanceled(); // внутри фоновой операции
void onCanceled(); // в UI-потоке
}
80.
DOWNLOADIMAGETASKprivate class DomnloadImageTask extends AsyncTask<String, Void, Bitmap> {
@Override
protected void onPreExecute() {
mProgressBar.setVisibility(View.VISIBLE);
}
@Override
protected Bitmap doInBackground(String… strings) {
return getBitmap(strings[0]);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
mImageView.setImageBitmap(bitmap);
mProgressBar.setVisibility(View.INVISIBLE);
}
}
81.
ИЗБАВЛЯЕМСЯ ОТ УТЕЧКИprivate class DomnloadImageTask extends AsyncTask<String, Void, Bitmap> {
private WeakReference<MainActivity> mActivityWeakReference;
private DomnloadImageTask(MainActivity activity) {
mActivityWeakReference = new WeakReference<>(activity);
}
//----@Override
protected void onPostExecute(Bitmap bitmap) {
MainActivity activity = mActivityWeakReference.get();
if (activity != null) {
activity.getImageView().setImageBitmap(bitmap);
activity.getProgressBar().setVisibility(View.INVISIBLE);
}
}
82.
О ПРОЦЕССАХ И ПОТОКАХКаждое приложение в Android по умолчанию работает в своем
собственном процессе, в своей области памяти. В память чужого
процесса попасть нельзя, это гарантируется системой.
Первый поток, запущенный в процессе, называется главным потоком.
Главный поток – main thread – UI thread – в контексте Android
синонимы.
MainThread не уничтожается сам
Почему MainThread не умирает?
•Благодаря Looper.
Что делает Looper?
•Looper в бесконечном цикле проверяет MessageQueue.
83.
HAMER = HANDLER + MESSAGE + RUNNABLEЧто такое MessageQueue?
•Очередь объектов Message, которые нужно обработать.
Как сообщения попадают в MessageQueue?
•Handler, связанный с Looper, отправляет сообщения в очередь
Looper.
Кто обрабатывает сообщения?
•В сообщении есть ссылка на Handler, который это сообщение
должен обработать
84.
HANDLERHandler handler = new Handler();
Handler bgHandler = new Handler(bgLooper);
Handler mainHandler = new Handler(Looper.getMainLooper());
handler.post (new Runnable() {
@Override
public void run() {
}
});
handler.postDelayed (new Runnable(), 4000);
85.
MESSAGEmHandler.obtainMessage(MESSAGE_WHAT, dataObject).sendToTarget ();
mHandler = new Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_WHAT: {
DataObject dataObject = (DataObject) msg.obj;
doSomething(dataObject);
msg.recycle() } } } };
mHandler.post (new Runnable() {
@Override
public void run() {
doSomething(dataObject); } });
Message message = Message.obtain(mAnotherHandler,
MESSAGE_ANOTHER_WHAT, anotherObject);
86.
LOADERMANAGERLoader – это API, позволяющее загружать данные из
различных источников (сервер, БД, content-provider) вне
зависимости от жизненного цикла.
LoaderManager – класс, который запускает Loader. Для
получения экземпляра менеджера – LoaderManager
getSupportLoaderManager()
Loader<D> initLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<D> callback)
Loader<D> restartLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<D> callback)
87.
LOADERCALLBACKSLoader<D> restartLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<D> callback)
boolean hasRunningLoaders();
Loader<D> getLoader(int id);
void destroyLoader(int id);
LoaderManager.LoaderCallbacks содержит методы, которые
вызываются при определенных событиях у лоадера
onCreateLoader(int, Bundle)
onLoadFinished(Loader<D>, D)
onLoaderReset(Loader<D>)
Loader – базовый класс. Наследуемся от него, если нужно
сделать какую-то уникальную реализацию. Иначе можно
использовать системные реализации.
88.
CONTENTPROVIDERSContentProvider – механизм, который инкапсулирует доступ к
данным, дополнительно позволяя обращаться к ним из разных
процессов.
ContentProvider позволяет безопасно делиться данными с
другими приложениями
Телефонная книга
•Чаты
•Банки
89.
СПОСОБЫ ХРАНЕНИЯ ДАННЫХ В ANDROIDPersistence:
•Общие сведения (SharedPreferences)
•Файлы
• Internal Storage
• External Storage
•БД / ORM
90.
EXTERNAL STORAGE И БАЗЫ ДАННЫХ•External Storage (неструктурированные данные)
• SD-карта
•Базы данных и ORM-обёртки (структурированные данные)
• SQLite
91.
РАЗРЕШЕНИЯ ВО ВРЕМЯ ВЫПОЛНЕНИЯ•обычные (normal)
•опасные (dangerous)
public static int checkSelfPermission(@NonNull Context context,
@NonNull String permission)
•Менеджер пакетов.PERMISSION_GRANTED
•Менеджер пакетов.PERMISSION_DENIED
java.lang.Исключение безопасности
ActivityCompat.requestPermissions(this, new String[]
{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_CODE);
92.
СЕРВЕР•физический
Почтовый
клиент
•программный
Почтовый
клиент
Почтовый
клиент
Почтовый
сервер
Почтовый
клиент
Почтовый
клиент
Почтовый
клиент
93.
HTTPHyperText Transfer Protocol
•Запрос к серверу (Request)
•Ответ от сервера (Response)
1. Стартовая строка запроса
URI METHOD HTTP/VERSION
METHOD – это метод HTTP-запроса
URI – идентификатор ресурса
VERSION – версия протокола.
2. Заголовки (Headers)
3. Тело сообщения (Body)
94.
OKHTTP3•HttpURLConnection
•HTTP-клиент Apache
1. Пул соединений
2. Gziping
3. Кэширование
4. Восстановление после сетевых ошибок
5. Редиректы
6. Повторы
7. Поддержка синхронных и асинхронных вызовов
8. Перехватчики
95.
RETROFIT2Основные возможности Retrofit:
•Вся сила OkHttp
•API Interfaces
•Call Adapters
•Converters
•Задание параметров URL и поддержка параметров запроса
•Преобразование объектов в тело запроса
•Многостраничный запрос и загрузка файлов
96.
РЕАКТИВНОЕ ПРОГРАММИРОВАНИЕИспользование потоков:
•Переменные
•Пользовательский ввод
•Свойства
•Кэш
•Структуры данных
Реализации реактивного подхода:
•ReactJS
•Bacon.js
•ReactiveX
97.
ДОСТОИНСТВА РЕАКТИВНОГО ПРОГРАММИРОВАНИЯЕсли вы не хотите...
...писать много, а делать мало
То в реактивном подходе...
...пиши мало, делай много!
...часами дебажить простую логику
...обеспечение связи данных друг с
другом!
...чтобы всё по умолчанию тупило
...оптимизация потоков данных по
умолчанию!
...чтобы приложение падало
целиком и полностью
...проводить махинации с
индикаторами ожидания
...создавать переиспользуемые
компоненты
...никакой exception не пройдет мимо!
...индикаторы ожидания сами
появляются, где надо!
...компоненты будут
переиспользуемыми по умолчанию!
98.
RXJAVA2Тип источника
Flowable<T>
Описание источника
Поддерживает backpressure.
Observable<T>
Излучает 0 или n элементов и завершается с успехом
или ошибкой. Не поддерживает backpressure.
Single<T>
Излучает либо один элемент, либо событие ошибки.
Реактивная версия вызова метода.
Maybe<T>
Успешно с элементом, или без элемента, или без ошибок.
Реактивная версия типа Optional.
Либо завершается с успехом, либо с событием ошибки.
Он никогда не излучает элементы. Реактивная версия
типа Runnable.
Completable
99.
РЕАКТИВНАЯ СХЕМА ДАННЫХИсточники:
•горячие (hot)
•холодные (cold)
https://github.com/Froussios/Intro-ToRxJava/blob/master/Part%203%20%20Taming%20the%20sequence/6.%20Hot%20and%20Cold%20o
bservables.md
100.
ИСТОЧНИКИBackpressure (обратное давление) – явление, которое можно
встретить в порождающем потоке, где некоторые асинхронные
операции не могут обрабатывать значения достаточно быстро
и нуждаются в замедлении работы производителя.
https://habr.com/ru/post/336268/
101.
OBSERVER И SUBSCRIBERpublic interface Observer<T> {
void onSubscribe(@NonNull Disposable d);
void onNext(@NonNull T t);
void onError(@NonNull Throwable e);
void onComplete();
}
102.
ПРАКТИКА С RXJAVA2implementation 'io.reactivex.rxjava2:rxjava:2.1.8’
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1’
Observable.just("Привет!")
Observable.fromIterable()
Observable.fromArray()
Observable.fromCallable()
Observable.fromFuture()
Observable.interval()
subscribe()
subscribe(Consumer<? super T> onNext)
103.
СМЕШИВАНИЕ ОТОБРАЖЕНИЯ И ЛОГИКИ@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView.setAdapter(mProjectsAdapter);
ApiUtils.getApiService().getProjects(BuildConfig.API_QUERY)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe( response -> {
mErrorView.setVisibility(View.GONE);
mRecyclerView.setVisibility(View.VISIBLE);
mProjectsAdapter.addData(response.getProjects(), true);
},
throwable -> {
mErrorView.setVisibility(View.VISIBLE);
mRecyclerView.setVisibility(View.GONE); });}
104.
MVCТонких Артём Петрович, 1978
― Model – бизнес-логика
― View – отображение
―Controller – обработка ввода
View!=android.view.View
105.
SOLIDS – Принцип единой ответственности (SRP)
A class should have only one reason to change.
Каждый объект должен иметь одну ответственность и эта
ответственность должна быть полностью инкапсулирована в класс.
O – Принцип открытости/закрытости (OCP)
Software entities (classes, modules, functions, etc) should be open for
extension, but closed for modification.
Программные сущности (классы, модули, функции и т.д.) должны
быть открыты для расширения, но закрыты для изменения
L – Принцип заменяемости (LSP)
I – Принцип разделения интерфейсов (ISP)
D – Принцип инверсии зависимостей (DIP)
106.
ПРИМЕР ОТКРЫТОСТИ-ЗАКРЫТОСТИpublic abstract class AbstractEntity { … }
public class AccountEntity extends AbstractEntity { … }
public class RoleEntity extends AbstractEntity { … }
public interface IRepository<AbstractEntity>{
void save(AbstractEntity entity); }
public class AccountRepository implements IRepository<AccountEntity>{
public void save(AccountEntity entity) {
// специфические действия для AccountEntity
}
}
public class RoleRepository implements IRepository<RoleEntity>{
public void save(RoleEntity abstractEntity) {
// специфические действия для RoleEntity
}
}
107.
ПРИМЕР ПРИНЦИПА ИНВЕРСИИ ЗАВИСИМОСТЕЙpublic class Reporter
{
public void sendReports()
{
ReportBuilder reportBuilder = new ReportBuilder();
List<Report> reports = reportBuilder.createReports();
if (reports.size() == 0)
throw new NoReportsException();
EmailReportSender reportSender = new
EmailReportSender();
for (Report report : reports)
{
reportSender.send(report);
}
}}
108.
MVPpublic interface SampleView {
void setData(List<Item>items);
}
public class SamplePresenter {
private SampleView mView;
public SamplePresenter(SampleView view) {
mView = view;
}
void loadData() {
//load data from server
}
}
mView.setData(items);
109.
SAMPLEACTIVITY (MVP)public class SampleActivity extends AppCompatActivity
implements SampleView {
private SamplePresenter mPresenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPresenter = new SamplePresenter(this);
button.SetOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPresenter.loadData(); } }); }
@Override
public void setData(List<Item> items) { }
}
110.
MOXYpublic class ProjectsFragment
extends MvpAppCompatFragment
implements ProjectsView {
@InjectPresenter
public ProjectsPresenter mPresenter;
@ProvidePresenter
ProjectsPresenter providePresenter() {
D someDependency = new D;
return new
ProjectsPresenter(someDependency);
}
//остальной код
}
111.
MVPVIEWpublic interface ProjectsView extends BaseView, MvpView {
@StateStrategyType(value = SingleStateStrategy.class)
void showProjects(@NonNull List<Project> projects);
@StateStrategyType(value = SkipStrategy.class)
void openProfileFragment(@NonNull String username);
}
AddToEndStrategy – выполнить команду и добавить команду в конец
очереди
AddToEndSingleStrategy – выполнить команду, добавить ее в конец
очереди и удалить все ее предыдущие экземпляры
SingleStateStrategy – выполнить команду, очистить очередь и
добавить в нее команду
SkipStrategy – выполнить команду
OneExecuteStrategy – выполнить команду
при первой возможности
112.
MVVMModel – данные и методы их получения, сохранения, обработки
View – визуальное представление данных, экран
ViewModel – абстракция представления, прослойка между View и
Model
public class ViewModel {
private String mUserName;
void updateUserName() {
mUserName = “Тонких Артём Петрович”;
}
}
113.
ПРЕИМУЩЕСТВА И НЕДОСТАТКИ MVVMПреимущества:
•Компоненты слабо связаны
•Databinding уменьшает количество кода
•Несколько View → одна ViewModel
Недостатки:
•Показ Toast и диалогов
•Показ анимаций или данных с задержкой
•Необходимость обработки команды во View
114.
DATABINDING LIBRARY<?xml version=“1.0” encoding=“utf-8”?>
<layout xmlns:android=“http://schemas.android.com/apk/res/android”>
<data>
<variable name=“user” type=“ru.rosdistant.edu.User” />
</data>
<LinearLayout
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:orientation=“vertical”>
<TextView android:text=“Username” />
<TextView android:text=“@{user.name}” />
</LinearLayout>
</layout>
115.
ВОЗМОЖНОСТИ РАЗМЕТКИpublic class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AcMainBinding binding = DataBindingUtil.
setContentView(this, R.layout.ac_main);
User user = new User(“Тонких Артём Петрович”);
binding.setUser(user); } }
android:visibility=“@{user.shouldShow ? V.VISIBLE : V.GONE }”
<import alias=“V” type=“android.view.View” />
android:src=“@{user.avatar ?? @drawable/placeholder}”
android:src=“@{user.avatar != null ? user.avatar : @drawable/placeholder}”
116.
ОБРАБОТКА НАЖАТИЙandroid:src=“@{user.avatar ?? @drawable/placeholder}”
android:src=“@{user.avatar != null ? user.avatar : @drawable/placeholder}”
Mathematical + - / * %
String concatenation +
Logical && ||
Binary & | ^
Unary + - ! ~
Shift >> >>> <<
Comparison == >
< >= <= instance of
Grouping ()
НЕ ПОДДЕРЖИВАЕТСЯ
Literals – character, String, new
numeric, null
this
Cast
super
Method calls
<T> doSomething(T data)
Field access
Array e[]
Ternary operator ?:
117.
ССЫЛКА НА МЕТОДpublic class UserActions { public void onUserClick(View view { } }
<data> <variable name=“actions” type=“ru.rosdistant.edu.UserActions”/>
</data>
android:onClick=“@{actions::onUserClick}”
UserActions userActions = new UserActions(); binding.setActions(userActions);
public class ProfileManager { public boolean sort(List<User> users { }}
<data> <import type=“ru.rosdistant.edu.User”/>
<import type=“java.util.List”/>
<variable name=“profileManager”
type=“ru.rosdistant.edu.ProfileManager”/>
<variable name=“users” type=“List<User>”/>
</data>
android:onLongClick=“@{()->profileManager.sort(users)}”
118.
ПРИВЯЗКА LISTENERandroid:onLongClick=“@{()->profileManager.sort(users)}”
public class CustomAdapter {
@BindingAdapter({“bind:imageUrl”})
public static void loadImage(ImageView view, String url) {
Picasso.with(view.getContext()).load(url). Into(view);
}
}
<ImageView
android:layout_width=“@dimen/avatar_size”
android:layout_height=“@dimen/avatar_size”
app:image_Url=“@{user.avatarUrl}” />
119.
ANDROID ARCHITECTURE COMPONENTSActivity / Fragment
ViewModel
LiveData3
Repository
Model
Room
SQLite
Remote Data Source
Retrofit
webservice
120.
ОСНОВНЫЕ ТЕЗИСЫ- Нельзя хранить контент или состояние в компонентах, и
компоненты не должны зависеть друг от друга
- Интерфейс и контент приложения должны заполняться,
опираясь на модель. Модель не должна зависеть от
компонентов андроид
121.
VIEWMODELActivity created
Activity rotated
finish()
Finished
onCreate
onStart
onResume
onPause
onStop
onDestroy
onCreate
onStart
onResume
onPause
onStop
onDestroy
MyViewModel model =
ViewModelProviders.of(this).
get(MyViewModel.class);
ViewModel
Scope
onCleared()
Во ViewModel не должно
быть ссылок на объекты с
жизненным циклом!
122.
LIFECYCLESTATES
INITIALIZED
(initial start)
DESTROYED
(dead state)
CREATED
STARTED
RESUMED
ON_CREATE
ON_START
ON_RESUME
EVENTS
ON_PAUSE
ON_STOP
ON_DESTROY
INITIALIZED
(initial start)
STATES
DESTROYED
(dead state)
CREATED
STARTED
RESUMED
123.
LIVEDATA. PAGING LIBRARYpublic class NameViewModel extends ViewModel {
private MutableLiveData<String> mName;
public MutableLiveData<String> getName() {
if (mCurrentName == null) {
mCurrentName = new MutableLiveData<String>();
}
return mCurrentName;
}
public void setCurrentName(String name) {
mCurrentName.postValue(name);
}
}
124.
DEPENDENCY INVERSION PRINCIPLE125.
ПРЯМОЙ И ОБРАТНЫЙ ПОТОКИ УПРАВЛЕНИЯ126.
INVERSION OF CONTROLФреймворк
Custom module
2
3
1
библиотеки
Приложение В
custom module
1
Приложение А
2
3
127.
ЦЕЛИ IOCОтделение вызова от реализации задачи
Концентрация на самой задаче, а не на обработке вызова
Отсутствие допущений о том, как система работает внутри,
использование вместо этого общепринятых контрактов
128.
DEPENDENCY INJECTIONclass A {
// A – клиент
private B mB; // B – зависимость (сервис)
A() { mB = new BImpl();
// клиент сам разрешает свою зависимость
}
A(B b) {
// клиент получает зависимость извне
mB = b;
}
void action();
Data data = mB.getDataForAction();
// использование функциональности B
}
}
B b = new BImpl();
// создание конкретной реализации
A a = new A(b);
// внедрение реализации B в A
129.
ПРИМЕР DEPENDENCY INJECTIONpublic class Car {
private Engine mEngine;
private Tires mTires;
public Car() {
mEngine = new
AutoEngine(“V2.0”);
mTires = new Michelin();
}
public void start(Settings s) {
s.configure ();
mEngine.run(s);
}
}
public Car (Engine engine, Tires tires) {
mEngine = engine;
mTires = tires;
}
// --String engineCapacity = “V2.0”;
Engine engine = new
AutoEngine(engineCapacity);
Tires tires = new Michelin();
mOrdinaryCar = new Car (engine,
tires);
mOrdinaryCar.showDiagnosticsData();
// ---
130.
ТИПЫ ВНЕДРЯЕМЫХ ЗАВИСИМОСТЕЙConstructor Injection – внедрение через конструктор
обязательной зависимости
Property (Setter) Injection – переопределение через сеттер
необязательной зависимости
Method Injection – передача в метод зависимости, которая
используется только в этом методе
131.
ДОБАВЛЕНИЕ DAGGER 2 В ПРОЕКТdependencies {
implementation
‘com.google.dagger:dagger-android:2.11’
implementation
‘com.google.dagger:dagger-android-support:2.11’
annotationProcessor
‘com.google.dagger:dagger-android-processor:2.11’
annotationProcessor
‘com.google.dagger:dagger-compiler:2.11’
}
132.
ПРОСТОЙ ПРИМЕР@Inject
public SimpleRepository() { … }
@Singleton
@Component
public interface SimpleComponent {void inject(SampleActivity activity);}
public class SampleActivity extends Activity {
@Inject
SimpleRepository repository;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AppComponent component =
DaggerAppComponent.builder().build;
component.inject(this); }
}
133.
NAMED. QUALIFIER. SCOPES134.
CLEAN ARCHITECTURE135.
USER•Быть тестируемой
•Не зависеть от UI
•Не зависеть от БД
•Не зависеть от внешних фреймворков и библиотек
•Не зависеть от какого-либо внешнего сервиса
136.
Model viewpresenter
Data
layer
Domain
layer
Boundaries
Presentation
layer
Interactions
РЕАЛИЗАЦИЯ
Regular Java
Objects
Repository
pattern
137.
РЕАЛИЗАЦИЯdata grade
presentation.gradle
apply plugin:
‘com.android.library’
{…}
implementation project (‘:domain’)
apply plugin:
‘com.android.library’
{…}
implementation project (‘:domain’)
implementation project (‘:data’)
domain grade
apply plugin: ‘java’
138.
СХЕМА РАБОТЫ ДАННЫХView
Presenter
Service
Use Case
Repository
public interface Interactor <P, R> {
interface Callback<R> {
void onSuccess(R object);
void onError(Throwable
throwable);
}
void execute(P parameter,
Callback<R> callback);
}
139.
ДОСТОИНСТВА CLEAN ARCHITECTURE- Модульное разделение
- Dependency Rule
- Тестирование
- Domain-слой
- В Presentation-слое можно использовать любой MV-паттерн
- Кастомизация
- Хорошее комьюнити
- Большое количество гайдов
- Достаточно богатая база исходных кодов и шаблонов с примерами
140.
НЕДОСТАТКИ CLEAN ARCHITECTURE- Громоздкость
- Порог вхождения
Когда использовать Clean Architecture?
- Много бизнес-логики
- Действительно большое приложение
- Необходимо качественное покрытие тестами
- Постоянный рост или нужен задел на будущее
- Планируется мультиплатформа
Когда следует воздержаться?
- Простое приложение, в котором практически нет логики
Программирование