From ea4e8ab8a27a9f81ac49102e22f56ab171eb5a65 Mon Sep 17 00:00:00 2001 From: Mikhail Yukhnin Date: Wed, 10 Jun 2020 17:56:27 +0400 Subject: [PATCH 1/7] =?UTF-8?q?=D0=9D=D0=B0=D1=87=D0=B0=D0=BB=D0=BE=20?= =?UTF-8?q?=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=8B=20=D0=BD=D0=B0=D0=B4=20MVP?= =?UTF-8?q?=20(Moxy)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 4 ++- .../callbacks/PersonDetailsCallback.java | 11 +++++++ .../lesson1/callbacks/PersonListCallback.java | 9 ++++++ .../presenters/ContactListPresenter.java | 32 +++++++++++++++++++ .../lesson1/repository/ContactRepository.java | 10 ++++-- .../ContactRepositoryFromSystem.java | 10 +++--- .../lesson1/ui/views/ContactDetailsView.java | 17 ++++++++++ .../lesson1/ui/views/ContactListView.java | 10 ++++++ 8 files changed, 95 insertions(+), 8 deletions(-) create mode 100644 app/src/main/java/com/a65apps/yuhnin/lesson1/callbacks/PersonDetailsCallback.java create mode 100644 app/src/main/java/com/a65apps/yuhnin/lesson1/callbacks/PersonListCallback.java create mode 100644 app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java create mode 100644 app/src/main/java/com/a65apps/yuhnin/lesson1/ui/views/ContactDetailsView.java create mode 100644 app/src/main/java/com/a65apps/yuhnin/lesson1/ui/views/ContactListView.java diff --git a/app/build.gradle b/app/build.gradle index 7a8bfa5..ab7641e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -25,11 +25,13 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'androidx.appcompat:appcompat:1.0.2' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.legacy:legacy-support-v4:1.0.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + implementation 'com.arello-mobile:moxy:1.5.5' + implementation 'tech.schoolhelper:moxy-x-androidx:1.7.0' + annotationProcessor 'com.arello-mobile:moxy-compiler:1.5.5' } diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/callbacks/PersonDetailsCallback.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/callbacks/PersonDetailsCallback.java new file mode 100644 index 0000000..b39c8f4 --- /dev/null +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/callbacks/PersonDetailsCallback.java @@ -0,0 +1,11 @@ +package com.a65apps.yuhnin.lesson1.callbacks; + +import com.a65apps.yuhnin.lesson1.pojo.ContactInfoModel; +import com.a65apps.yuhnin.lesson1.pojo.PersonModelAdvanced; + +import java.util.List; + +public interface PersonDetailsCallback { + void getPersonDetails(PersonModelAdvanced personModel); + void getPersonContacts(List contactList); +} diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/callbacks/PersonListCallback.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/callbacks/PersonListCallback.java new file mode 100644 index 0000000..9619c1c --- /dev/null +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/callbacks/PersonListCallback.java @@ -0,0 +1,9 @@ +package com.a65apps.yuhnin.lesson1.callbacks; + +import com.a65apps.yuhnin.lesson1.pojo.PersonModelCompact; + +import java.util.List; + +public interface PersonListCallback { + void getPersonList(List personList); +} diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java new file mode 100644 index 0000000..761cd23 --- /dev/null +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java @@ -0,0 +1,32 @@ +package com.a65apps.yuhnin.lesson1.presenters; + +import com.a65apps.yuhnin.lesson1.callbacks.PersonListCallback; +import com.a65apps.yuhnin.lesson1.pojo.PersonModelCompact; +import com.a65apps.yuhnin.lesson1.repository.ContactRepository; +import com.a65apps.yuhnin.lesson1.ui.views.ContactListView; +import com.arellomobile.mvp.MvpPresenter; + +import java.util.List; + +public class ContactListPresenter extends MvpPresenter implements PersonListCallback { + ContactRepository contactRepository; + + public ContactListPresenter(ContactRepository contactRepository) { + this.contactRepository = contactRepository; + } + + void getContactList() { + contactRepository.getAllPersons(this); + } + + @Override + public void onDestroy() { + this.contactRepository = null; + super.onDestroy(); + } + + @Override + public void getPersonList(List personList) { + getViewState().getContactList(personList); + } +} diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepository.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepository.java index f509bf8..44efe4e 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepository.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepository.java @@ -3,19 +3,23 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.a65apps.yuhnin.lesson1.callbacks.PersonDetailsCallback; +import com.a65apps.yuhnin.lesson1.callbacks.PersonListCallback; import com.a65apps.yuhnin.lesson1.pojo.ContactInfoModel; import com.a65apps.yuhnin.lesson1.pojo.PersonModelAdvanced; import com.a65apps.yuhnin.lesson1.pojo.PersonModelCompact; +import com.a65apps.yuhnin.lesson1.ui.listeners.ContactsResultListener; +import com.a65apps.yuhnin.lesson1.ui.listeners.PersonListResultListener; import java.util.List; public interface ContactRepository { @Nullable - List getAllPersons(); + List getAllPersons(PersonListCallback callback); @NonNull - List getContactByPerson(String id); + List getContactByPerson(PersonDetailsCallback callback, String id); @Nullable - PersonModelAdvanced getPersonById(String id); + PersonModelAdvanced getPersonById(PersonDetailsCallback callback, String id); } diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepositoryFromSystem.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepositoryFromSystem.java index 6a57da7..557b502 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepositoryFromSystem.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepositoryFromSystem.java @@ -10,6 +10,8 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.a65apps.yuhnin.lesson1.callbacks.PersonDetailsCallback; +import com.a65apps.yuhnin.lesson1.callbacks.PersonListCallback; import com.a65apps.yuhnin.lesson1.pojo.ContactInfoModel; import com.a65apps.yuhnin.lesson1.pojo.ContactType; import com.a65apps.yuhnin.lesson1.pojo.PersonModelAdvanced; @@ -35,7 +37,7 @@ public static synchronized ContactRepositoryFromSystem getInstance(Context conte @Nullable @Override - public List getAllPersons() { + public List getAllPersons (PersonListCallback callback) { ArrayList personList = new ArrayList<>(); ContentResolver contentResolver = context.getContentResolver(); Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, @@ -66,7 +68,7 @@ public List getAllPersons() { @NonNull @Override - public List getContactByPerson(String personId) { + public List getContactByPerson(PersonDetailsCallback callback, String personId) { List contactInfoModels = new ArrayList(); try { List phoneNumbers = getPhoneList(personId, context.getContentResolver()); @@ -92,8 +94,9 @@ public List getContactByPerson(String personId) { } + @Nullable @Override - public PersonModelAdvanced getPersonById(String personId) { + public PersonModelAdvanced getPersonById(PersonDetailsCallback callback, String personId) { PersonModelAdvanced personModelAdvanced = null; ContentResolver contentResolver = context.getContentResolver(); Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI,null, @@ -276,5 +279,4 @@ private List getEmailList(String personId, ContentResolver con } return emailList; } - } diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/views/ContactDetailsView.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/views/ContactDetailsView.java new file mode 100644 index 0000000..51d6ef1 --- /dev/null +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/views/ContactDetailsView.java @@ -0,0 +1,17 @@ +package com.a65apps.yuhnin.lesson1.ui.views; + +import com.a65apps.yuhnin.lesson1.pojo.ContactInfoModel; +import com.a65apps.yuhnin.lesson1.pojo.PersonModelAdvanced; +import com.arellomobile.mvp.MvpView; +import com.arellomobile.mvp.viewstate.strategy.AddToEndSingleStrategy; +import com.arellomobile.mvp.viewstate.strategy.StateStrategyType; + +import java.util.List; + +public interface ContactDetailsView extends MvpView { + @StateStrategyType(AddToEndSingleStrategy.class) + void getContactDetails(PersonModelAdvanced personModel); + + @StateStrategyType(AddToEndSingleStrategy.class) + void getContactsInfo(List listOfContacts); +} diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/views/ContactListView.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/views/ContactListView.java new file mode 100644 index 0000000..29bbc21 --- /dev/null +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/views/ContactListView.java @@ -0,0 +1,10 @@ +package com.a65apps.yuhnin.lesson1.ui.views; + +import com.a65apps.yuhnin.lesson1.pojo.PersonModelCompact; +import com.arellomobile.mvp.MvpView; + +import java.util.List; + +public interface ContactListView extends MvpView { + void getContactList(List personList); +} From 4a9686142c17a6fa78a669d652e900a61ed58124 Mon Sep 17 00:00:00 2001 From: Mikhail Yukhnin Date: Thu, 11 Jun 2020 10:52:34 +0400 Subject: [PATCH 2/7] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3=20=D0=BF=D0=BE=20=D0=BF=D0=B0=D1=82?= =?UTF-8?q?=D1=82=D0=B5=D1=80=D0=BD=D1=83=20MVP=20=20-=20=D0=A3=D0=B4?= =?UTF-8?q?=D0=B0=D0=BB=D0=B5=D0=BD=20=D1=81=D0=B5=D1=80=D0=B2=D0=B8=D1=81?= =?UTF-8?q?=20=20-=20=D0=92=D1=81=D1=8F=20=D0=B7=D0=B0=D0=B3=D1=80=D1=83?= =?UTF-8?q?=D0=B7=D0=BA=D0=B0=20=D0=BA=D0=BE=D0=BD=D1=82=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D0=B2=20=D0=B2=20=D1=80=D0=B5=D0=BF=D0=BE=D0=B7=D0=B8?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D0=B8=D0=B8=20=20-=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=B1=D0=B8=D0=B1=D0=BB?= =?UTF-8?q?=D0=B8=D0=BE=D1=82=D0=B5=D0=BA=D0=B0=20Moxy=20=20-=20=D0=9E?= =?UTF-8?q?=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 22 ++- app/build.gradle | 9 +- app/src/main/AndroidManifest.xml | 5 - .../com/a65apps/yuhnin/lesson1/Constants.java | 1 + .../callbacks/PersonDetailsCallback.java | 4 +- .../presenters/ContactDetailsPresenter.java | 46 +++++ .../presenters/ContactListPresenter.java | 7 +- .../lesson1/repository/ContactRepository.java | 14 +- .../repository/ContactRepositoryFakeImp.java | 73 +++++--- .../ContactRepositoryFromSystem.java | 172 ++++++++++-------- .../lesson1/services/DataFetchService.java | 91 --------- .../lesson1/ui/activities/MainActivity.java | 17 +- .../ui/adapters/PersonListAdapter.java | 1 - .../ui/fragments/ContactDetailsFragment.java | 149 ++++++--------- .../ui/fragments/ContactListFragment.java | 96 +++------- .../ui/listeners/ContactsResultListener.java | 8 - .../listeners/PersonListResultListener.java | 9 - .../ui/listeners/PersonResultListener.java | 7 - .../{ui => }/views/ContactDetailsView.java | 2 +- .../{ui => }/views/ContactListView.java | 2 +- 20 files changed, 317 insertions(+), 418 deletions(-) create mode 100644 app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java delete mode 100644 app/src/main/java/com/a65apps/yuhnin/lesson1/services/DataFetchService.java delete mode 100644 app/src/main/java/com/a65apps/yuhnin/lesson1/ui/listeners/ContactsResultListener.java delete mode 100644 app/src/main/java/com/a65apps/yuhnin/lesson1/ui/listeners/PersonListResultListener.java delete mode 100644 app/src/main/java/com/a65apps/yuhnin/lesson1/ui/listeners/PersonResultListener.java rename app/src/main/java/com/a65apps/yuhnin/lesson1/{ui => }/views/ContactDetailsView.java (93%) rename app/src/main/java/com/a65apps/yuhnin/lesson1/{ui => }/views/ContactListView.java (84%) diff --git a/README.md b/README.md index 4220c34..3081800 100644 --- a/README.md +++ b/README.md @@ -32,12 +32,12 @@ ### Результат | Главный экран | Детали контакта | | ------ | ------ | -| ![Детали](https://i.imgur.com/AavdvqJ.jpg) |![Главный экран](https://i.imgur.com/rhFKsrB.jpg) +| ![Список](https://i.imgur.com/uVBhVfT.jpg) |![Главный экран](https://i.imgur.com/rhFKsrB.jpg) ## Задание №3. Сервисы Необходимо написать привязанный сервис, который будет иметь публичное API предоставляющее список контактов. Список контактов пока захардкодить в константу Сервис должен предоставлять список контактов на другом потоке программы - т.е. должен создавать поток для загрузки списка контактов -#### Сценарий использования: +### Сценарий использования: - Главная активность привязывается к сервису с помощью bindService - Получает публичный интерфейс сервиса - Предоставляет публичный интерфейс сервиса фрагментам @@ -55,11 +55,11 @@ ## Задание №5. Content - Использование поставщика контактов -## Задание +### Задание Необходимо реализовать загрузку контактов пользователя из поставщика контактов В существующем методе загрузки списка контактов - получать список всех контактов пользователя из поставщика контактов В существующем методе загрузки деталей контакта по ID - получать все необходимые данные контакта из поставщика контактов по ID -## Проделанная работа. +### Проделанная работа. Добавлен класс-репозиторий контактов ContactRepositoryFromSystem, который позволяет получать список всех контактов, список телефонов и адресов эл.почты и подробную информацию о контакте. @@ -77,3 +77,17 @@ Пришлось отказаться от разделения на Фамилию Имя и Отчество. Вместо этого использовать объединенное поле `String displayName;` Помимо этого переделал фейковый репозиторий контактов `ContactRepositoryFakeImp` для работы с новой моделью контакта. + +## Задание №6. Рефакторинг проекта по паттерну MVP + +### Задание + +Необходимо произвести рефакторинг существующего кода приложения с использованием на выбор: 1. MVVM - использовать компоненты от Google: ViewModel + LiveData 2. MVP - в качестве библиотеки использовать Moxy В рамках рефакторинга необходимо будет удалить существующий сервис загрузки контактов, и всю работу по загрузке контактов из сервиса вынести в репозиторий, который будет использоваться в ViewModel/Presenter соответственно выбранного паттерна проектирования. + +### Проделанная работа. + +Произвел рефакторинг и изменение архитектуры на MVP с использованием библиотеки Moxy. + +Удалил существующий сервис загрузки контактов + +Всю работу по загрузке контактов перенс в репозиторий \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index ab7641e..207fa95 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -31,7 +31,10 @@ dependencies { testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' - implementation 'com.arello-mobile:moxy:1.5.5' - implementation 'tech.schoolhelper:moxy-x-androidx:1.7.0' - annotationProcessor 'com.arello-mobile:moxy-compiler:1.5.5' + + implementation "com.arello-mobile:moxy:1.4.5" + annotationProcessor "com.arello-mobile:moxy-compiler:1.4.5" + implementation ('tech.schoolhelper:moxy-x-androidx:1.7.0'){ + exclude group: 'tech.schoolhelper', module:'moxy-x' + } } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f40dc36..87a4ac4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,11 +11,6 @@ android:supportsRtl="true" android:theme="@style/AppTheme"> - - contactList); + void onFetchPersonDetails(PersonModelAdvanced personModel); + void onFetchPersonContacts(List contactList); } diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java new file mode 100644 index 0000000..5d86faa --- /dev/null +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java @@ -0,0 +1,46 @@ +package com.a65apps.yuhnin.lesson1.presenters; + +import com.a65apps.yuhnin.lesson1.callbacks.PersonDetailsCallback; +import com.a65apps.yuhnin.lesson1.pojo.ContactInfoModel; +import com.a65apps.yuhnin.lesson1.pojo.PersonModelAdvanced; +import com.a65apps.yuhnin.lesson1.repository.ContactRepository; +import com.a65apps.yuhnin.lesson1.views.ContactDetailsView; +import com.arellomobile.mvp.MvpPresenter; + +import java.util.List; + +public class ContactDetailsPresenter extends MvpPresenter implements PersonDetailsCallback { + ContactRepository contactRepository; + + public ContactDetailsPresenter(ContactRepository contactRepository) { + this.contactRepository = contactRepository; + } + + public void requestContactsByPerson(String personId) { + if (contactRepository != null) { + contactRepository.getContactByPerson(this, personId); + } + } + + public void requestPersonDetails(String personId) { + if (contactRepository != null) + contactRepository.getPersonById(this, personId); + + } + @Override + public void onDestroy() { + this.contactRepository = null; + super.onDestroy(); + } + + @Override + public void onFetchPersonDetails(PersonModelAdvanced personModel) { + getViewState().getContactDetails(personModel); + } + + @Override + public void onFetchPersonContacts(List contactList) { + getViewState().getContactsInfo(contactList); + } + +} diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java index 761cd23..73444a1 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java @@ -3,7 +3,7 @@ import com.a65apps.yuhnin.lesson1.callbacks.PersonListCallback; import com.a65apps.yuhnin.lesson1.pojo.PersonModelCompact; import com.a65apps.yuhnin.lesson1.repository.ContactRepository; -import com.a65apps.yuhnin.lesson1.ui.views.ContactListView; +import com.a65apps.yuhnin.lesson1.views.ContactListView; import com.arellomobile.mvp.MvpPresenter; import java.util.List; @@ -15,8 +15,9 @@ public ContactListPresenter(ContactRepository contactRepository) { this.contactRepository = contactRepository; } - void getContactList() { - contactRepository.getAllPersons(this); + public void requestContactList() { + if (contactRepository != null) + contactRepository.getAllPersons(this); } @Override diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepository.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepository.java index 44efe4e..213d6c3 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepository.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepository.java @@ -5,21 +5,13 @@ import com.a65apps.yuhnin.lesson1.callbacks.PersonDetailsCallback; import com.a65apps.yuhnin.lesson1.callbacks.PersonListCallback; -import com.a65apps.yuhnin.lesson1.pojo.ContactInfoModel; -import com.a65apps.yuhnin.lesson1.pojo.PersonModelAdvanced; -import com.a65apps.yuhnin.lesson1.pojo.PersonModelCompact; -import com.a65apps.yuhnin.lesson1.ui.listeners.ContactsResultListener; -import com.a65apps.yuhnin.lesson1.ui.listeners.PersonListResultListener; import java.util.List; public interface ContactRepository { - @Nullable - List getAllPersons(PersonListCallback callback); + void getAllPersons(PersonListCallback callback); - @NonNull - List getContactByPerson(PersonDetailsCallback callback, String id); + void getContactByPerson(PersonDetailsCallback callback, String id); - @Nullable - PersonModelAdvanced getPersonById(PersonDetailsCallback callback, String id); + void getPersonById(PersonDetailsCallback callback, String id); } diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepositoryFakeImp.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepositoryFakeImp.java index 6c569f0..a545212 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepositoryFakeImp.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepositoryFakeImp.java @@ -3,15 +3,16 @@ import android.content.ContentResolver; import android.content.Context; import android.net.Uri; -import android.util.Log; import com.a65apps.yuhnin.lesson1.R; +import com.a65apps.yuhnin.lesson1.callbacks.PersonDetailsCallback; +import com.a65apps.yuhnin.lesson1.callbacks.PersonListCallback; import com.a65apps.yuhnin.lesson1.pojo.ContactInfoModel; import com.a65apps.yuhnin.lesson1.pojo.ContactType; import com.a65apps.yuhnin.lesson1.pojo.PersonModelAdvanced; import com.a65apps.yuhnin.lesson1.pojo.PersonModelCompact; -import java.text.ParseException; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; @@ -41,16 +42,11 @@ private void setContext(Context context) { public ContactRepositoryFakeImp() { - try { - createPersons(); - createContacts(); - }catch (ParseException ex) { - Log.e(LOG_TAG, "Ошибка формата даты рождения при создании списка контактов. " + - ex.getMessage()); - } + createPersons(); + createContacts(); } - private void createPersons() throws ParseException{ + private void createPersons() { personModelAdvanceds.add(new PersonModelAdvanced( "1", "Гагарин Юрий Алексеевич", @@ -98,30 +94,57 @@ private void createContacts() { } @Override - public List getAllPersons() { - return personModelCompacts; + public void getAllPersons(PersonListCallback callback) { + final WeakReference weakReference = new WeakReference(callback); + new Thread(new Runnable() { + @Override + public void run() { + PersonListCallback local = weakReference.get(); + if (local != null) { + local.getPersonList(personModelCompacts); + } + } + }).start(); } @Override - public List getContactByPerson(String id) { - List foundContacts = new ArrayList(); - for (ContactInfoModel contact : contactInfoModels) { - if (contact.getPersonId().equals(id)) { - foundContacts.add(contact); + public void getContactByPerson(PersonDetailsCallback callback, final String personId) { + final WeakReference weakReference = new WeakReference(callback); + new Thread(new Runnable() { + @Override + public void run() { + List foundContacts = new ArrayList(); + for (ContactInfoModel contact : contactInfoModels) { + if (contact.getPersonId().equals(personId)) { + foundContacts.add(contact); + } + } + PersonDetailsCallback local = weakReference.get(); + if (local != null) { + local.onFetchPersonContacts(contactInfoModels); + } } - } - return foundContacts; + }).start(); } @Override - public PersonModelAdvanced getPersonById(String id) { - for (PersonModelAdvanced personModelAdvanced : personModelAdvanceds) { - if (personModelAdvanced.getId().equals(id)) { - return personModelAdvanced; + public void getPersonById(PersonDetailsCallback callback, final String personId) { + final WeakReference weakReference = new WeakReference(callback); + new Thread(new Runnable() { + @Override + public void run() { + for (PersonModelAdvanced personModelAdvanced : personModelAdvanceds) { + if (personModelAdvanced.getId().equals(personId)) { + PersonDetailsCallback local = weakReference.get(); + if (local != null) { + local.onFetchPersonDetails(personModelAdvanced); + } + } + } + } - } - return null; + }).start(); } public Uri resourceToUri(int resID) { diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepositoryFromSystem.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepositoryFromSystem.java index 557b502..a114fbe 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepositoryFromSystem.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepositoryFromSystem.java @@ -7,7 +7,6 @@ import android.provider.ContactsContract; import android.util.Log; -import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.a65apps.yuhnin.lesson1.callbacks.PersonDetailsCallback; @@ -17,6 +16,7 @@ import com.a65apps.yuhnin.lesson1.pojo.PersonModelAdvanced; import com.a65apps.yuhnin.lesson1.pojo.PersonModelCompact; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; @@ -35,95 +35,117 @@ public static synchronized ContactRepositoryFromSystem getInstance(Context conte return instance; } - @Nullable @Override - public List getAllPersons (PersonListCallback callback) { - ArrayList personList = new ArrayList<>(); - ContentResolver contentResolver = context.getContentResolver(); - Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, - null, null, null, null); - try { - if (cursor != null) { - while (cursor.moveToNext()) { + public void getAllPersons (PersonListCallback callback) { + final WeakReference weakReference = new WeakReference<>(callback); + new Thread(new Runnable() { + @Override + public void run() { + PersonListCallback local = weakReference.get(); + if (local != null) { + ArrayList personList = new ArrayList<>(); + ContentResolver contentResolver = context.getContentResolver(); + Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, + null, null, null, null); try { - String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); - String displaName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); - String strPhotoUri = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI)); - Log.d(LOG_TAG, "Найден контакт: id=" + id + "; ФИО: " + displaName + " фото="+strPhotoUri); - personList.add(new PersonModelCompact(id, displaName, strPhotoUri==null ? null : Uri.parse(strPhotoUri))); - //Log.d(LOG_TAG, "Контакт добавлен"); - } catch (Exception e) { - Log.d(LOG_TAG, "Произошла ошибка получения контакта: " + e.getMessage()); + if (cursor != null) { + while (cursor.moveToNext()) { + try { + String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); + String displaName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); + String strPhotoUri = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI)); + Log.d(LOG_TAG, "Найден контакт: id=" + id + "; ФИО: " + displaName + " фото="+strPhotoUri); + personList.add(new PersonModelCompact(id, displaName, strPhotoUri==null ? null : Uri.parse(strPhotoUri))); + //Log.d(LOG_TAG, "Контакт добавлен"); + } catch (Exception e) { + Log.d(LOG_TAG, "Произошла ошибка получения контакта: " + e.getMessage()); + } + } + } + } finally { + if (cursor != null) { + cursor.close(); + } } + local.getPersonList(personList); } } - } finally { - if (cursor != null) { - cursor.close(); - } - } - return personList; + }).start(); } - @NonNull @Override - public List getContactByPerson(PersonDetailsCallback callback, String personId) { - List contactInfoModels = new ArrayList(); - try { - List phoneNumbers = getPhoneList(personId, context.getContentResolver()); - if (phoneNumbers != null) { - contactInfoModels.addAll(phoneNumbers); - } - } catch (Exception e) { - Log.e(LOG_TAG, "Произошла ошибка чтения списка телефонов контакта id=" + personId + - ". Текст ошибки: " + e.getMessage()); - } - - try { - List emails = getEmailList(personId, context.getContentResolver()); - if (emails != null) { - contactInfoModels.addAll(emails); + public void getContactByPerson(PersonDetailsCallback callback, final String personId) { + final WeakReference weakReference = new WeakReference(callback); + new Thread(new Runnable() { + @Override + public void run() { + List contactInfoModels = new ArrayList(); + try { + List phoneNumbers = getPhoneList(personId, context.getContentResolver()); + if (phoneNumbers != null) { + contactInfoModels.addAll(phoneNumbers); + } + } catch (Exception e) { + Log.e(LOG_TAG, "Произошла ошибка чтения списка телефонов контакта id=" + personId + + ". Текст ошибки: " + e.getMessage()); + } + try { + List emails = getEmailList(personId, context.getContentResolver()); + if (emails != null) { + contactInfoModels.addAll(emails); + } + } catch (Exception e) { + Log.e(LOG_TAG, "Произошла ошибка чтения списка адресов эл.почты контакта " + personId + + ". Текст ошибки: " + e.getMessage()); + } + PersonDetailsCallback local = weakReference.get(); + if (local != null) { + local.onFetchPersonContacts(contactInfoModels); + } } - } catch (Exception e) { - Log.e(LOG_TAG, "Произошла ошибка чтения списка адресов эл.почты контакта " + personId + - ". Текст ошибки: " + e.getMessage()); - } - - return contactInfoModels; + }).start(); } - @Nullable @Override - public PersonModelAdvanced getPersonById(PersonDetailsCallback callback, String personId) { - PersonModelAdvanced personModelAdvanced = null; - ContentResolver contentResolver = context.getContentResolver(); - Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI,null, - ContactsContract.Contacts._ID + " = " + personId,null ,null); - try{ - if (cursor != null) { - cursor.moveToNext(); - String displaName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY)); - String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); - String strPhotoUri = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI)); - String dateBirthDay = getDateBirthday(id, contentResolver); - String description = getCompanyName(id, contentResolver); - personModelAdvanced = new PersonModelAdvanced( - personId, - displaName, - description, - strPhotoUri == null ? null : Uri.parse(strPhotoUri), - dateBirthDay); - } - } catch (Exception e) { - Log.e(LOG_TAG, "Ошибка получения информации о контакте" + e.getMessage()); - } finally { - if (cursor != null) { - cursor.close(); + public void getPersonById(PersonDetailsCallback callback, final String personId) { + final WeakReference weakReference = new WeakReference(callback); + new Thread(new Runnable() { + @Override + public void run() { + PersonModelAdvanced personModelAdvanced = null; + ContentResolver contentResolver = context.getContentResolver(); + Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI,null, + ContactsContract.Contacts._ID + " = " + personId,null ,null); + try{ + if (cursor != null) { + cursor.moveToNext(); + String displaName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY)); + String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); + String strPhotoUri = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI)); + String dateBirthDay = getDateBirthday(id, contentResolver); + String description = getCompanyName(id, contentResolver); + personModelAdvanced = new PersonModelAdvanced( + personId, + displaName, + description, + strPhotoUri == null ? null : Uri.parse(strPhotoUri), + dateBirthDay); + } + } catch (Exception e) { + Log.e(LOG_TAG, "Ошибка получения информации о контакте" + e.getMessage()); + } finally { + if (cursor != null) { + cursor.close(); + } + } + PersonDetailsCallback local = weakReference.get(); + if (local != null) { + local.onFetchPersonDetails(personModelAdvanced); + } } - } - return personModelAdvanced; + }).start(); } /** diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/services/DataFetchService.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/services/DataFetchService.java deleted file mode 100644 index a0919c9..0000000 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/services/DataFetchService.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.a65apps.yuhnin.lesson1.services; - -import android.app.Service; -import android.content.Intent; -import android.os.Binder; -import android.os.IBinder; - -import com.a65apps.yuhnin.lesson1.pojo.ContactInfoModel; -import com.a65apps.yuhnin.lesson1.pojo.PersonModelAdvanced; -import com.a65apps.yuhnin.lesson1.pojo.PersonModelCompact; -import com.a65apps.yuhnin.lesson1.repository.ContactRepositoryFromSystem; -import com.a65apps.yuhnin.lesson1.ui.listeners.ContactsResultListener; -import com.a65apps.yuhnin.lesson1.ui.listeners.PersonListResultListener; -import com.a65apps.yuhnin.lesson1.ui.listeners.PersonResultListener; - -import java.lang.ref.WeakReference; -import java.util.List; -import java.util.Random; - -public class DataFetchService extends Service { - - // Экземпляр Binder для клиентов - private final IBinder mBinder = new LocalBinder(); - // Random number generator - private final Random mGenerator = new Random(); - - public DataFetchService() { - } - - - public class LocalBinder extends Binder { - public DataFetchService getService() { - return DataFetchService.this; - } - } - - @Override - public IBinder onBind(Intent intent) { - return mBinder; - } - - /** method for clients */ - public int getRandomNumber() { - return mGenerator.nextInt(100); - } - - public void fetchPersons(PersonListResultListener callback) { - final WeakReference ref = new WeakReference(callback); - new Thread(new Runnable() { - @Override - public void run() { - List personModelCompacts = ContactRepositoryFromSystem.getInstance(getApplicationContext()).getAllPersons(); - PersonListResultListener local = ref.get(); - if (local != null) { - local.onFetchPersonList(personModelCompacts); - } - } - }).start(); - } - - public void fetchPersonById(PersonResultListener callback, final String personId) { - final WeakReference ref = new WeakReference(callback); - new Thread(new Runnable() { - @Override - public void run() { - PersonModelAdvanced personModelAdvanced = ContactRepositoryFromSystem.getInstance(getApplicationContext()).getPersonById(personId); - PersonResultListener local = ref.get(); - if (local != null) { - local.onFetchPersonModel(personModelAdvanced); - } - } - }).start(); - } - - public void fetchContactInfo(ContactsResultListener callback, final String personId) { - final WeakReference ref = new WeakReference(callback); - new Thread(new Runnable() { - @Override - public void run() { - List contactInfoModels = ContactRepositoryFromSystem - .getInstance(getApplicationContext()).getContactByPerson(personId); - ContactsResultListener local = ref.get(); - if (local != null) { - local.onFetchContacts(contactInfoModels); - } - } - }).start(); - } - - -} diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/activities/MainActivity.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/activities/MainActivity.java index fff2559..20d6618 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/activities/MainActivity.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/activities/MainActivity.java @@ -2,7 +2,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; @@ -23,30 +22,26 @@ import com.a65apps.yuhnin.lesson1.Constants; import com.a65apps.yuhnin.lesson1.R; -import com.a65apps.yuhnin.lesson1.services.DataFetchService; import com.a65apps.yuhnin.lesson1.ui.fragments.ContactDetailsFragment; import com.a65apps.yuhnin.lesson1.ui.fragments.ContactListFragment; import com.a65apps.yuhnin.lesson1.ui.fragments.RequestPermissonFragment; import com.a65apps.yuhnin.lesson1.ui.listeners.EventActionBarListener; import com.a65apps.yuhnin.lesson1.ui.listeners.OnPersonClickedListener; +import com.arellomobile.mvp.MvpAppCompatActivity; -public class MainActivity extends AppCompatActivity +public class MainActivity extends MvpAppCompatActivity implements OnPersonClickedListener, EventActionBarListener { final String LOG_TAG = "activity_application"; final String TAG_FRAGMENT_DETAILS = "TAG_FRAGMENT_DETAILS"; final String TAG_FRAGMENT_PERM_REQ = "TAG_FRAGMENT_PERM_REQ"; final String TAG_FRAGMENT_LIST = "TAG_FRAGMENT_LIST"; - boolean mBound = false; FragmentManager fragmentManager = getSupportFragmentManager(); @Nullable Toolbar toolbar; - @Nullable - DataFetchService mService; - @Override protected void onStart() { Log.d(LOG_TAG, "onStart start"); @@ -63,7 +58,7 @@ protected void onDestroy() { @Override protected void onCreate(Bundle savedInstanceState) { - Log.d(LOG_TAG, "onCreate strat"); + Log.d(LOG_TAG, "onCreate start"); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); toolbar = findViewById(R.id.toolbar); @@ -73,7 +68,7 @@ protected void onCreate(Bundle savedInstanceState) { int permissionStatus = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS); if (permissionStatus == PackageManager.PERMISSION_GRANTED) { if (fragmentManager.getFragments().isEmpty()) { - String id = getIntent().getStringExtra("KEY_PERSON_ID"); + String id = getIntent().getStringExtra(Constants.KEY_PERSON_ID); if (id != null && !id.isEmpty()) { сreateDetailsFragment(id); } else { @@ -116,7 +111,7 @@ private void createPersonListFragment() { */ private void сreateDetailsFragment(String personId) { Bundle bundle = new Bundle(); - bundle.putString("PERSON_ID", personId); + bundle.putString(Constants.KEY_PERSON_ID, personId); ContactDetailsFragment contactDetailsFragment = (ContactDetailsFragment) fragmentManager.findFragmentByTag(TAG_FRAGMENT_DETAILS); if (contactDetailsFragment == null) { // Фрагмент еще не создан @@ -216,7 +211,7 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis case Constants.CODE_PERMISSION_READ_CONTACTS: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(getApplicationContext(), getString(R.string.permission_granted), Toast.LENGTH_SHORT); - String id = getIntent().getStringExtra("KEY_PERSON_ID"); + String id = getIntent().getStringExtra(Constants.KEY_PERSON_ID); if (id != null && !id.isEmpty()) { сreateDetailsFragment(id); } else { diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/adapters/PersonListAdapter.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/adapters/PersonListAdapter.java index bccd240..2016a83 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/adapters/PersonListAdapter.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/adapters/PersonListAdapter.java @@ -37,7 +37,6 @@ public Object getItem(int i) { @Override public long getItemId(int i) { - // FIXME: не уверен, что так делать правильно. Но мне больше негде взять численный идентификтор return this.personList.get(i).getId().hashCode(); } diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactDetailsFragment.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactDetailsFragment.java index 3c7b1f6..c6c879b 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactDetailsFragment.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactDetailsFragment.java @@ -2,17 +2,12 @@ import android.app.AlarmManager; import android.app.PendingIntent; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.ServiceConnection; import android.os.Bundle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; - -import android.os.IBinder; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -24,25 +19,35 @@ import android.widget.ToggleButton; import com.a65apps.yuhnin.lesson1.BirthdayReminderReceiver; +import com.a65apps.yuhnin.lesson1.Constants; import com.a65apps.yuhnin.lesson1.R; import com.a65apps.yuhnin.lesson1.pojo.ContactInfoModel; import com.a65apps.yuhnin.lesson1.pojo.PersonModelAdvanced; -import com.a65apps.yuhnin.lesson1.services.DataFetchService; +import com.a65apps.yuhnin.lesson1.presenters.ContactDetailsPresenter; +import com.a65apps.yuhnin.lesson1.repository.ContactRepositoryFromSystem; import com.a65apps.yuhnin.lesson1.ui.adapters.ContactListAdapter; -import com.a65apps.yuhnin.lesson1.ui.listeners.ContactsResultListener; import com.a65apps.yuhnin.lesson1.ui.listeners.EventActionBarListener; -import com.a65apps.yuhnin.lesson1.ui.listeners.PersonResultListener; +import com.a65apps.yuhnin.lesson1.views.ContactDetailsView; +import com.arellomobile.mvp.MvpAppCompatFragment; +import com.arellomobile.mvp.presenter.InjectPresenter; +import com.arellomobile.mvp.presenter.ProvidePresenter; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.List; -public class ContactDetailsFragment extends Fragment - implements ContactsResultListener, PersonResultListener, CompoundButton.OnCheckedChangeListener { - static final String ARG_PARAM_PERSON_ID = "PERSON_ID"; +public class ContactDetailsFragment extends MvpAppCompatFragment + implements ContactDetailsView, CompoundButton.OnCheckedChangeListener { final String LOG_TAG = "details_fragment"; - boolean serviceBound = false; + // FIXME. Вопрос: все эти поля нужно присваивать null в onDestroy? Как быть с contactListPresenter? + // ----------------------------- + ImageView ivAvatar; + TextView tvFullname; + ListView lvContacts; + TextView tvDescription; + TextView tvBirthday; + ToggleButton toggleBtnRemindBirthday; @NonNull PersonModelAdvanced person; @@ -55,22 +60,20 @@ public class ContactDetailsFragment extends Fragment private String personId = ""; - @Nullable - DataFetchService mService; - @Nullable List contactInfoList; @Nullable private EventActionBarListener eventActionBarListener; - ImageView ivAvatar; - TextView tvFullname; - ListView lvContacts; - TextView tvDescription; - TextView tvBirthday; - ToggleButton toggleBtnRemindBirthday; + @InjectPresenter + ContactDetailsPresenter contactDetailsPresenter; + @ProvidePresenter + ContactDetailsPresenter providerContactDetailsPresenter(){ + return contactDetailsPresenter = new ContactDetailsPresenter(ContactRepositoryFromSystem.getInstance(getContext())); + } + // ------------------------------ public ContactDetailsFragment() { // Required empty public constructor @@ -95,12 +98,8 @@ public void onDetach() { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { - this.personId = getArguments().getString(ARG_PARAM_PERSON_ID); + this.personId = getArguments().getString(Constants.KEY_PERSON_ID); } - // Биндинг сервиса - Intent intent = new Intent(getActivity(), DataFetchService.class); - getActivity().bindService(intent, mConnection, Context.BIND_AUTO_CREATE); - } @Override @@ -124,7 +123,8 @@ public void onResume() { if (eventActionBarListener != null) { eventActionBarListener.setVisibleToolBarBackButton(true); } - requestContactsByPerson(); + contactDetailsPresenter.requestContactsByPerson(personId); + contactDetailsPresenter.requestPersonDetails(personId); requireActivity().setTitle(getString(R.string.toolbar_header_person_details)); super.onResume(); } @@ -138,23 +138,6 @@ public void onDestroyView() { super.onDestroyView(); } - @Override - public void onDestroy() { - if (serviceBound) { - getActivity().unbindService(mConnection); - serviceBound = false; - } - super.onDestroy(); - } - - public void requestContactsByPerson() { - if (mService != null) { - mService.fetchPersonById(this, personId); - mService.fetchContactInfo(this, personId); - Log.d(LOG_TAG, "Запрашиваем детали контакта и его контактную информацию"); - } - } - private void updateFields() { if (person == null) { Log.e(LOG_TAG, "Невозможно отобразить данные контакта person=null"); @@ -183,39 +166,6 @@ private void updateFields() { } - @Override - public void onFetchContacts(final List contactInfoList) { - this.contactInfoList = contactInfoList; - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - if (lvContacts != null && contactInfoList != null) { - ContactListAdapter contactListAdapter = new ContactListAdapter(getContext(), contactInfoList); - lvContacts.setAdapter(contactListAdapter); - } else { - Log.e(LOG_TAG, "onFetchContacts - Сервис вернул contactInfoList=null"); - } - } - }); - } - - @Override - public void onFetchPersonModel(final PersonModelAdvanced personModelAdvanced) { - this.person = personModelAdvanced; - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - if (personModelAdvanced != null) { - Log.d(LOG_TAG, "Создаем список контактных данных контакта " + person.getFullName()); - updateFields(); - } else { - Log.e(LOG_TAG, "onFetchPersonModel - Сервис вернул personModels=null"); - } - } - }); - - } - @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { @@ -223,7 +173,6 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { } else { Log.d(LOG_TAG, "Toggle uncheked"); } - setBirthdayReminderEnabled(isChecked); } @@ -276,19 +225,35 @@ private boolean checkBirthdayReminder() { PendingIntent.FLAG_NO_CREATE) != null); } - private ServiceConnection mConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName className, - IBinder service) { - DataFetchService.LocalBinder binder = (DataFetchService.LocalBinder) service; - mService = binder.getService(); - Log.d(LOG_TAG, "Сработал ServiceConnection - onServiceConnected"); - requestContactsByPerson(); - } + @Override + public void getContactDetails(PersonModelAdvanced personModel) { + this.person = personModel; + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + if (person != null) { + Log.d(LOG_TAG, "Создаем список контактных данных контакта " + person.getFullName()); + updateFields(); + } else { + Log.e(LOG_TAG, "onFetchPersonModel - репозиторий вернул personModels=null"); + } + } + }); + } - @Override - public void onServiceDisconnected(ComponentName arg0) { - Log.d(LOG_TAG, "Сработал ServiceConnection - onServiceDisconnected"); - } - }; + @Override + public void getContactsInfo(List listOfContacts) { + this.contactInfoList = listOfContacts; + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + if (lvContacts != null && contactInfoList != null) { + ContactListAdapter contactListAdapter = new ContactListAdapter(getContext(), contactInfoList); + lvContacts.setAdapter(contactListAdapter); + } else { + Log.e(LOG_TAG, "onFetchContacts - репозиторий вернул contactInfoList=null"); + } + } + }); + } } diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactListFragment.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactListFragment.java index e3838f2..a0175f9 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactListFragment.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactListFragment.java @@ -1,15 +1,10 @@ package com.a65apps.yuhnin.lesson1.ui.fragments; -import android.content.ComponentName; import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; import android.os.Bundle; import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import android.os.IBinder; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -19,40 +14,44 @@ import com.a65apps.yuhnin.lesson1.R; import com.a65apps.yuhnin.lesson1.pojo.PersonModelCompact; -import com.a65apps.yuhnin.lesson1.services.DataFetchService; +import com.a65apps.yuhnin.lesson1.presenters.ContactListPresenter; +import com.a65apps.yuhnin.lesson1.repository.ContactRepositoryFromSystem; import com.a65apps.yuhnin.lesson1.ui.adapters.PersonListAdapter; import com.a65apps.yuhnin.lesson1.ui.listeners.EventActionBarListener; import com.a65apps.yuhnin.lesson1.ui.listeners.OnPersonClickedListener; -import com.a65apps.yuhnin.lesson1.ui.listeners.PersonListResultListener; +import com.a65apps.yuhnin.lesson1.views.ContactListView; +import com.arellomobile.mvp.MvpAppCompatFragment; +import com.arellomobile.mvp.presenter.InjectPresenter; +import com.arellomobile.mvp.presenter.ProvidePresenter; import java.util.List; /** * Фрагмент списка контактов */ -// parent activity will implement this method to respond to click events - - - -public class ContactListFragment extends Fragment implements PersonListResultListener { +public class ContactListFragment extends MvpAppCompatFragment implements ContactListView { final String LOG_TAG = "contact_list_fragment"; - boolean serviceBound = false; ListView listviewPersons; @Nullable PersonListAdapter personListAdapter; - @Nullable - DataFetchService mService; - @Nullable private OnPersonClickedListener onPersonClickedListener; @Nullable private EventActionBarListener eventActionBarListener; + @InjectPresenter + ContactListPresenter contactListPresenter; + + @ProvidePresenter + ContactListPresenter providerContactListPresenter(){ + return contactListPresenter = new ContactListPresenter(ContactRepositoryFromSystem.getInstance(getContext())); + } + @Override public void onAttach(@Nullable Context context) { Log.d(LOG_TAG, "onAttach"); @@ -79,34 +78,10 @@ public ContactListFragment() { } - public void requestPersonList() { - if (mService != null) { - mService.fetchPersons(this); - Log.d(LOG_TAG, "Запрашиваем getPersonList"); - } - } - - private void createPersonsListView(final List personList) { - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - if (personList != null && listviewPersons != null) { - Log.d(LOG_TAG, "Создаем список контактов " + personList.size()); - personListAdapter = new PersonListAdapter(getActivity(), personList); - listviewPersons.setAdapter(personListAdapter); - } - } - }); - - } - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(LOG_TAG, "onCreate"); - // Биндинг сервиса - Intent intent = new Intent(getActivity(), DataFetchService.class); - getActivity().bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @Override @@ -125,6 +100,7 @@ public void onItemClick(AdapterView parent, View view, } }); requireActivity().setTitle(getString(R.string.toolbar_header_person_list)); + contactListPresenter.requestContactList(); return view; } @@ -147,35 +123,17 @@ public void onDestroyView() { } @Override - public void onDestroy() { - if (serviceBound) { - getActivity().unbindService(mConnection); - serviceBound = false; - } - super.onDestroy(); - } - - @Override - public void onFetchPersonList(List personList) { - Log.d(LOG_TAG, "ПОЛУЧЕНЫ ДАННЫЕ СПИСКА КОНТАКТОВ"); - createPersonsListView(personList); + public void getContactList(final List personList) { + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + if (personList != null && listviewPersons != null) { + Log.d(LOG_TAG, "Создаем список контактов " + personList.size()); + personListAdapter = new PersonListAdapter(getActivity(), personList); + listviewPersons.setAdapter(personListAdapter); + } + } + }); } - - private ServiceConnection mConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName className, - IBinder service) { - DataFetchService.LocalBinder binder = (DataFetchService.LocalBinder) service; - mService = binder.getService(); - serviceBound = true; - Log.d(LOG_TAG, "Сработал ServiceConnection - onServiceConnected"); - requestPersonList(); - } - - @Override - public void onServiceDisconnected(ComponentName arg0) { - Log.d(LOG_TAG, "Сработал ServiceConnection - onServiceDisconnected"); - } - }; } diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/listeners/ContactsResultListener.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/listeners/ContactsResultListener.java deleted file mode 100644 index 625f683..0000000 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/listeners/ContactsResultListener.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.a65apps.yuhnin.lesson1.ui.listeners; - -import com.a65apps.yuhnin.lesson1.pojo.ContactInfoModel; -import java.util.List; - -public interface ContactsResultListener { - void onFetchContacts(List contactInfoModels); -} diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/listeners/PersonListResultListener.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/listeners/PersonListResultListener.java deleted file mode 100644 index 8e9394a..0000000 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/listeners/PersonListResultListener.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.a65apps.yuhnin.lesson1.ui.listeners; - -import com.a65apps.yuhnin.lesson1.pojo.PersonModelCompact; - -import java.util.List; - -public interface PersonListResultListener { - void onFetchPersonList(List personModelCompacts); -} diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/listeners/PersonResultListener.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/listeners/PersonResultListener.java deleted file mode 100644 index 60fa909..0000000 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/listeners/PersonResultListener.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.a65apps.yuhnin.lesson1.ui.listeners; - -import com.a65apps.yuhnin.lesson1.pojo.PersonModelAdvanced; - -public interface PersonResultListener { - void onFetchPersonModel(PersonModelAdvanced personModelAdvanced); -} diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/views/ContactDetailsView.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/views/ContactDetailsView.java similarity index 93% rename from app/src/main/java/com/a65apps/yuhnin/lesson1/ui/views/ContactDetailsView.java rename to app/src/main/java/com/a65apps/yuhnin/lesson1/views/ContactDetailsView.java index 51d6ef1..5b5a429 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/views/ContactDetailsView.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/views/ContactDetailsView.java @@ -1,4 +1,4 @@ -package com.a65apps.yuhnin.lesson1.ui.views; +package com.a65apps.yuhnin.lesson1.views; import com.a65apps.yuhnin.lesson1.pojo.ContactInfoModel; import com.a65apps.yuhnin.lesson1.pojo.PersonModelAdvanced; diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/views/ContactListView.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/views/ContactListView.java similarity index 84% rename from app/src/main/java/com/a65apps/yuhnin/lesson1/ui/views/ContactListView.java rename to app/src/main/java/com/a65apps/yuhnin/lesson1/views/ContactListView.java index 29bbc21..66e2e90 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/views/ContactListView.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/views/ContactListView.java @@ -1,4 +1,4 @@ -package com.a65apps.yuhnin.lesson1.ui.views; +package com.a65apps.yuhnin.lesson1.views; import com.a65apps.yuhnin.lesson1.pojo.PersonModelCompact; import com.arellomobile.mvp.MvpView; From be1b3134f0a74c0d5faff159e580fa3aeb143802 Mon Sep 17 00:00:00 2001 From: Mikhail Yukhnin Date: Thu, 11 Jun 2020 12:03:35 +0400 Subject: [PATCH 3/7] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yuhnin/lesson1/presenters/ContactDetailsPresenter.java | 2 ++ .../yuhnin/lesson1/presenters/ContactListPresenter.java | 2 ++ .../java/com/a65apps/yuhnin/lesson1/views/ContactListView.java | 3 +++ 3 files changed, 7 insertions(+) diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java index 5d86faa..a233b96 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java @@ -5,10 +5,12 @@ import com.a65apps.yuhnin.lesson1.pojo.PersonModelAdvanced; import com.a65apps.yuhnin.lesson1.repository.ContactRepository; import com.a65apps.yuhnin.lesson1.views.ContactDetailsView; +import com.arellomobile.mvp.InjectViewState; import com.arellomobile.mvp.MvpPresenter; import java.util.List; +@InjectViewState public class ContactDetailsPresenter extends MvpPresenter implements PersonDetailsCallback { ContactRepository contactRepository; diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java index 73444a1..69bf2c0 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java @@ -4,10 +4,12 @@ import com.a65apps.yuhnin.lesson1.pojo.PersonModelCompact; import com.a65apps.yuhnin.lesson1.repository.ContactRepository; import com.a65apps.yuhnin.lesson1.views.ContactListView; +import com.arellomobile.mvp.InjectViewState; import com.arellomobile.mvp.MvpPresenter; import java.util.List; +@InjectViewState public class ContactListPresenter extends MvpPresenter implements PersonListCallback { ContactRepository contactRepository; diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/views/ContactListView.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/views/ContactListView.java index 66e2e90..77cfb2d 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/views/ContactListView.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/views/ContactListView.java @@ -2,9 +2,12 @@ import com.a65apps.yuhnin.lesson1.pojo.PersonModelCompact; import com.arellomobile.mvp.MvpView; +import com.arellomobile.mvp.viewstate.strategy.AddToEndSingleStrategy; +import com.arellomobile.mvp.viewstate.strategy.StateStrategyType; import java.util.List; public interface ContactListView extends MvpView { + @StateStrategyType(AddToEndSingleStrategy.class) void getContactList(List personList); } From bbb924a6e4c533f33216788096ef71a073e5e085 Mon Sep 17 00:00:00 2001 From: Mikhail Yukhnin Date: Thu, 11 Jun 2020 13:20:03 +0400 Subject: [PATCH 4/7] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=87=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B9=20-=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB?= =?UTF-8?q?=20NonNull=20=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=BE=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B8=20-=20=D0=9F=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D0=BD=D1=81=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80?= =?UTF-8?q?=D0=BA=D1=83=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D1=81=D0=BB=D0=B0=D0=B1=D0=BE=D0=B9=20=D1=81=D1=81?= =?UTF-8?q?=D1=8B=D0=BB=D0=BA=D0=B8=20-=20=D0=92=20=D1=80=D0=B5=D0=BF?= =?UTF-8?q?=D0=BE=D0=B7=D0=B8=D1=82=D0=BE=D1=80=D0=B8=D0=B9=20=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D0=B4=D0=B0=D0=B5=D1=82=D1=81=D1=8F=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=BD=D1=82=D0=B5=D0=BA=D1=81=D1=82=20=D0=BF=D1=80=D0=B8=D0=BB?= =?UTF-8?q?=D0=BE=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presenters/ContactDetailsPresenter.java | 11 ++- .../presenters/ContactListPresenter.java | 6 +- .../ContactRepositoryFromSystem.java | 90 +++++++++---------- .../lesson1/ui/activities/MainActivity.java | 4 +- .../ui/fragments/ContactDetailsFragment.java | 6 +- .../ui/fragments/ContactListFragment.java | 2 +- 6 files changed, 59 insertions(+), 60 deletions(-) diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java index a233b96..d1ac338 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java @@ -1,5 +1,7 @@ package com.a65apps.yuhnin.lesson1.presenters; +import androidx.annotation.NonNull; + import com.a65apps.yuhnin.lesson1.callbacks.PersonDetailsCallback; import com.a65apps.yuhnin.lesson1.pojo.ContactInfoModel; import com.a65apps.yuhnin.lesson1.pojo.PersonModelAdvanced; @@ -12,6 +14,7 @@ @InjectViewState public class ContactDetailsPresenter extends MvpPresenter implements PersonDetailsCallback { + @NonNull ContactRepository contactRepository; public ContactDetailsPresenter(ContactRepository contactRepository) { @@ -19,15 +22,11 @@ public ContactDetailsPresenter(ContactRepository contactRepository) { } public void requestContactsByPerson(String personId) { - if (contactRepository != null) { - contactRepository.getContactByPerson(this, personId); - } + contactRepository.getContactByPerson(this, personId); } public void requestPersonDetails(String personId) { - if (contactRepository != null) - contactRepository.getPersonById(this, personId); - + contactRepository.getPersonById(this, personId); } @Override public void onDestroy() { diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java index 69bf2c0..c30db69 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java @@ -1,5 +1,7 @@ package com.a65apps.yuhnin.lesson1.presenters; +import androidx.annotation.NonNull; + import com.a65apps.yuhnin.lesson1.callbacks.PersonListCallback; import com.a65apps.yuhnin.lesson1.pojo.PersonModelCompact; import com.a65apps.yuhnin.lesson1.repository.ContactRepository; @@ -11,6 +13,7 @@ @InjectViewState public class ContactListPresenter extends MvpPresenter implements PersonListCallback { + @NonNull ContactRepository contactRepository; public ContactListPresenter(ContactRepository contactRepository) { @@ -18,8 +21,7 @@ public ContactListPresenter(ContactRepository contactRepository) { } public void requestContactList() { - if (contactRepository != null) - contactRepository.getAllPersons(this); + contactRepository.getAllPersons(this); } @Override diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepositoryFromSystem.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepositoryFromSystem.java index a114fbe..748dd76 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepositoryFromSystem.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepositoryFromSystem.java @@ -80,27 +80,27 @@ public void getContactByPerson(PersonDetailsCallback callback, final String pers new Thread(new Runnable() { @Override public void run() { - List contactInfoModels = new ArrayList(); - try { - List phoneNumbers = getPhoneList(personId, context.getContentResolver()); - if (phoneNumbers != null) { - contactInfoModels.addAll(phoneNumbers); - } - } catch (Exception e) { - Log.e(LOG_TAG, "Произошла ошибка чтения списка телефонов контакта id=" + personId + - ". Текст ошибки: " + e.getMessage()); - } - try { - List emails = getEmailList(personId, context.getContentResolver()); - if (emails != null) { - contactInfoModels.addAll(emails); - } - } catch (Exception e) { - Log.e(LOG_TAG, "Произошла ошибка чтения списка адресов эл.почты контакта " + personId + - ". Текст ошибки: " + e.getMessage()); - } PersonDetailsCallback local = weakReference.get(); if (local != null) { + List contactInfoModels = new ArrayList(); + try { + List phoneNumbers = getPhoneList(personId, context.getContentResolver()); + if (phoneNumbers != null) { + contactInfoModels.addAll(phoneNumbers); + } + } catch (Exception e) { + Log.e(LOG_TAG, "Произошла ошибка чтения списка телефонов контакта id=" + personId + + ". Текст ошибки: " + e.getMessage()); + } + try { + List emails = getEmailList(personId, context.getContentResolver()); + if (emails != null) { + contactInfoModels.addAll(emails); + } + } catch (Exception e) { + Log.e(LOG_TAG, "Произошла ошибка чтения списка адресов эл.почты контакта " + personId + + ". Текст ошибки: " + e.getMessage()); + } local.onFetchPersonContacts(contactInfoModels); } } @@ -114,34 +114,34 @@ public void getPersonById(PersonDetailsCallback callback, final String personId) new Thread(new Runnable() { @Override public void run() { - PersonModelAdvanced personModelAdvanced = null; - ContentResolver contentResolver = context.getContentResolver(); - Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI,null, - ContactsContract.Contacts._ID + " = " + personId,null ,null); - try{ - if (cursor != null) { - cursor.moveToNext(); - String displaName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY)); - String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); - String strPhotoUri = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI)); - String dateBirthDay = getDateBirthday(id, contentResolver); - String description = getCompanyName(id, contentResolver); - personModelAdvanced = new PersonModelAdvanced( - personId, - displaName, - description, - strPhotoUri == null ? null : Uri.parse(strPhotoUri), - dateBirthDay); - } - } catch (Exception e) { - Log.e(LOG_TAG, "Ошибка получения информации о контакте" + e.getMessage()); - } finally { - if (cursor != null) { - cursor.close(); - } - } PersonDetailsCallback local = weakReference.get(); if (local != null) { + PersonModelAdvanced personModelAdvanced = null; + ContentResolver contentResolver = context.getContentResolver(); + Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI,null, + ContactsContract.Contacts._ID + " = " + personId,null ,null); + try{ + if (cursor != null) { + cursor.moveToNext(); + String displaName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY)); + String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); + String strPhotoUri = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI)); + String dateBirthDay = getDateBirthday(id, contentResolver); + String description = getCompanyName(id, contentResolver); + personModelAdvanced = new PersonModelAdvanced( + personId, + displaName, + description, + strPhotoUri == null ? null : Uri.parse(strPhotoUri), + dateBirthDay); + } + } catch (Exception e) { + Log.e(LOG_TAG, "Ошибка получения информации о контакте" + e.getMessage()); + } finally { + if (cursor != null) { + cursor.close(); + } + } local.onFetchPersonDetails(personModelAdvanced); } } diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/activities/MainActivity.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/activities/MainActivity.java index 20d6618..7ee16e5 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/activities/MainActivity.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/activities/MainActivity.java @@ -2,6 +2,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; @@ -27,9 +28,8 @@ import com.a65apps.yuhnin.lesson1.ui.fragments.RequestPermissonFragment; import com.a65apps.yuhnin.lesson1.ui.listeners.EventActionBarListener; import com.a65apps.yuhnin.lesson1.ui.listeners.OnPersonClickedListener; -import com.arellomobile.mvp.MvpAppCompatActivity; -public class MainActivity extends MvpAppCompatActivity +public class MainActivity extends AppCompatActivity implements OnPersonClickedListener, EventActionBarListener { final String LOG_TAG = "activity_application"; diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactDetailsFragment.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactDetailsFragment.java index c6c879b..f676991 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactDetailsFragment.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactDetailsFragment.java @@ -40,8 +40,7 @@ public class ContactDetailsFragment extends MvpAppCompatFragment implements ContactDetailsView, CompoundButton.OnCheckedChangeListener { final String LOG_TAG = "details_fragment"; - // FIXME. Вопрос: все эти поля нужно присваивать null в onDestroy? Как быть с contactListPresenter? - // ----------------------------- + ImageView ivAvatar; TextView tvFullname; ListView lvContacts; @@ -71,9 +70,8 @@ public class ContactDetailsFragment extends MvpAppCompatFragment @ProvidePresenter ContactDetailsPresenter providerContactDetailsPresenter(){ - return contactDetailsPresenter = new ContactDetailsPresenter(ContactRepositoryFromSystem.getInstance(getContext())); + return contactDetailsPresenter = new ContactDetailsPresenter(ContactRepositoryFromSystem.getInstance(getActivity().getApplicationContext())); } - // ------------------------------ public ContactDetailsFragment() { // Required empty public constructor diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactListFragment.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactListFragment.java index a0175f9..0fbd98e 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactListFragment.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactListFragment.java @@ -49,7 +49,7 @@ public class ContactListFragment extends MvpAppCompatFragment implements Contact @ProvidePresenter ContactListPresenter providerContactListPresenter(){ - return contactListPresenter = new ContactListPresenter(ContactRepositoryFromSystem.getInstance(getContext())); + return contactListPresenter = new ContactListPresenter(ContactRepositoryFromSystem.getInstance(getActivity().getApplicationContext())); } @Override From bb4b00188352b1ea14ba372dc0018551bf730daf Mon Sep 17 00:00:00 2001 From: Mikhail Yukhnin Date: Thu, 11 Jun 2020 15:04:18 +0400 Subject: [PATCH 5/7] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B6=D0=B5=D1=81=D1=82=D0=BA=D0=B8=D1=85=20?= =?UTF-8?q?=D1=81=D1=81=D1=8B=D0=BB=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ContactRepositoryFromSystem.java | 136 +++++++++--------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepositoryFromSystem.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepositoryFromSystem.java index 748dd76..51e35d0 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepositoryFromSystem.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepositoryFromSystem.java @@ -41,32 +41,32 @@ public void getAllPersons (PersonListCallback callback) { new Thread(new Runnable() { @Override public void run() { - PersonListCallback local = weakReference.get(); - if (local != null) { - ArrayList personList = new ArrayList<>(); - ContentResolver contentResolver = context.getContentResolver(); - Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, - null, null, null, null); - try { - if (cursor != null) { - while (cursor.moveToNext()) { - try { - String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); - String displaName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); - String strPhotoUri = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI)); - Log.d(LOG_TAG, "Найден контакт: id=" + id + "; ФИО: " + displaName + " фото="+strPhotoUri); - personList.add(new PersonModelCompact(id, displaName, strPhotoUri==null ? null : Uri.parse(strPhotoUri))); - //Log.d(LOG_TAG, "Контакт добавлен"); - } catch (Exception e) { - Log.d(LOG_TAG, "Произошла ошибка получения контакта: " + e.getMessage()); - } + ArrayList personList = new ArrayList<>(); + ContentResolver contentResolver = context.getContentResolver(); + Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, + null, null, null, null); + try { + if (cursor != null) { + while (cursor.moveToNext()) { + try { + String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); + String displaName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); + String strPhotoUri = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI)); + Log.d(LOG_TAG, "Найден контакт: id=" + id + "; ФИО: " + displaName + " фото="+strPhotoUri); + personList.add(new PersonModelCompact(id, displaName, strPhotoUri==null ? null : Uri.parse(strPhotoUri))); + //Log.d(LOG_TAG, "Контакт добавлен"); + } catch (Exception e) { + Log.d(LOG_TAG, "Произошла ошибка получения контакта: " + e.getMessage()); } } - } finally { - if (cursor != null) { - cursor.close(); - } } + } finally { + if (cursor != null) { + cursor.close(); + } + } + PersonListCallback local = weakReference.get(); + if (local != null) { local.getPersonList(personList); } } @@ -80,27 +80,27 @@ public void getContactByPerson(PersonDetailsCallback callback, final String pers new Thread(new Runnable() { @Override public void run() { - PersonDetailsCallback local = weakReference.get(); - if (local != null) { - List contactInfoModels = new ArrayList(); - try { - List phoneNumbers = getPhoneList(personId, context.getContentResolver()); - if (phoneNumbers != null) { - contactInfoModels.addAll(phoneNumbers); - } - } catch (Exception e) { - Log.e(LOG_TAG, "Произошла ошибка чтения списка телефонов контакта id=" + personId + - ". Текст ошибки: " + e.getMessage()); + List contactInfoModels = new ArrayList(); + try { + List phoneNumbers = getPhoneList(personId, context.getContentResolver()); + if (phoneNumbers != null) { + contactInfoModels.addAll(phoneNumbers); } - try { - List emails = getEmailList(personId, context.getContentResolver()); - if (emails != null) { - contactInfoModels.addAll(emails); - } - } catch (Exception e) { - Log.e(LOG_TAG, "Произошла ошибка чтения списка адресов эл.почты контакта " + personId + - ". Текст ошибки: " + e.getMessage()); + } catch (Exception e) { + Log.e(LOG_TAG, "Произошла ошибка чтения списка телефонов контакта id=" + personId + + ". Текст ошибки: " + e.getMessage()); + } + try { + List emails = getEmailList(personId, context.getContentResolver()); + if (emails != null) { + contactInfoModels.addAll(emails); } + } catch (Exception e) { + Log.e(LOG_TAG, "Произошла ошибка чтения списка адресов эл.почты контакта " + personId + + ". Текст ошибки: " + e.getMessage()); + } + PersonDetailsCallback local = weakReference.get(); + if (local != null) { local.onFetchPersonContacts(contactInfoModels); } } @@ -114,34 +114,34 @@ public void getPersonById(PersonDetailsCallback callback, final String personId) new Thread(new Runnable() { @Override public void run() { + PersonModelAdvanced personModelAdvanced = null; + ContentResolver contentResolver = context.getContentResolver(); + Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI,null, + ContactsContract.Contacts._ID + " = " + personId,null ,null); + try{ + if (cursor != null) { + cursor.moveToNext(); + String displaName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY)); + String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); + String strPhotoUri = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI)); + String dateBirthDay = getDateBirthday(id, contentResolver); + String description = getCompanyName(id, contentResolver); + personModelAdvanced = new PersonModelAdvanced( + personId, + displaName, + description, + strPhotoUri == null ? null : Uri.parse(strPhotoUri), + dateBirthDay); + } + } catch (Exception e) { + Log.e(LOG_TAG, "Ошибка получения информации о контакте" + e.getMessage()); + } finally { + if (cursor != null) { + cursor.close(); + } + } PersonDetailsCallback local = weakReference.get(); if (local != null) { - PersonModelAdvanced personModelAdvanced = null; - ContentResolver contentResolver = context.getContentResolver(); - Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI,null, - ContactsContract.Contacts._ID + " = " + personId,null ,null); - try{ - if (cursor != null) { - cursor.moveToNext(); - String displaName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY)); - String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); - String strPhotoUri = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI)); - String dateBirthDay = getDateBirthday(id, contentResolver); - String description = getCompanyName(id, contentResolver); - personModelAdvanced = new PersonModelAdvanced( - personId, - displaName, - description, - strPhotoUri == null ? null : Uri.parse(strPhotoUri), - dateBirthDay); - } - } catch (Exception e) { - Log.e(LOG_TAG, "Ошибка получения информации о контакте" + e.getMessage()); - } finally { - if (cursor != null) { - cursor.close(); - } - } local.onFetchPersonDetails(personModelAdvanced); } } From d674cc646ac56e782b6906d9c55a6fbfc987e834 Mon Sep 17 00:00:00 2001 From: Mikhail Yukhnin Date: Mon, 15 Jun 2020 16:08:01 +0400 Subject: [PATCH 6/7] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=87=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=B9=20=20-=20=D0=A0=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=B0=20=D1=81=20=D0=BF=D0=BE=D1=82=D0=BE=D0=BA=D0=B0=D0=BC?= =?UTF-8?q?=D0=B8=20=D0=B2=D1=8B=D0=BD=D0=B5=D1=81=D0=B5=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=B2=20=D0=BF=D1=80=D0=B5=D0=B7=D0=B5=D0=BD=D1=82=D0=B5=D1=80?= =?UTF-8?q?=20=20-=20=D0=A0=D0=B5=D0=BF=D0=BE=D0=B7=D0=B8=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=B9=20=D0=BF=D0=BE=D0=BC=D0=B5=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=20=D0=BA=D0=B0=D0=BA=20NonNull?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presenters/ContactDetailsPresenter.java | 29 +++++++++++----- .../presenters/ContactListPresenter.java | 21 +++++++----- .../ui/fragments/ContactDetailsFragment.java | 34 +++++++------------ .../ui/fragments/ContactListFragment.java | 15 +++----- 4 files changed, 50 insertions(+), 49 deletions(-) diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java index d1ac338..a3754c4 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java @@ -1,5 +1,8 @@ package com.a65apps.yuhnin.lesson1.presenters; +import android.os.Handler; +import android.os.Looper; + import androidx.annotation.NonNull; import com.a65apps.yuhnin.lesson1.callbacks.PersonDetailsCallback; @@ -16,9 +19,12 @@ public class ContactDetailsPresenter extends MvpPresenter implements PersonDetailsCallback { @NonNull ContactRepository contactRepository; + @NonNull + Handler handler; public ContactDetailsPresenter(ContactRepository contactRepository) { this.contactRepository = contactRepository; + this.handler = new Handler(Looper.getMainLooper()); } public void requestContactsByPerson(String personId) { @@ -28,20 +34,25 @@ public void requestContactsByPerson(String personId) { public void requestPersonDetails(String personId) { contactRepository.getPersonById(this, personId); } - @Override - public void onDestroy() { - this.contactRepository = null; - super.onDestroy(); - } @Override - public void onFetchPersonDetails(PersonModelAdvanced personModel) { - getViewState().getContactDetails(personModel); + public void onFetchPersonDetails(final PersonModelAdvanced personModel) { + handler.post(new Runnable() { + @Override + public void run() { + getViewState().getContactDetails(personModel); + } + }); } @Override - public void onFetchPersonContacts(List contactList) { - getViewState().getContactsInfo(contactList); + public void onFetchPersonContacts(final List contactList) { + handler.post(new Runnable() { + @Override + public void run() { + getViewState().getContactsInfo(contactList); + } + }); } } diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java index c30db69..68b1f0b 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java @@ -1,5 +1,8 @@ package com.a65apps.yuhnin.lesson1.presenters; +import android.os.Handler; +import android.os.Looper; + import androidx.annotation.NonNull; import com.a65apps.yuhnin.lesson1.callbacks.PersonListCallback; @@ -15,9 +18,12 @@ public class ContactListPresenter extends MvpPresenter implements PersonListCallback { @NonNull ContactRepository contactRepository; + @NonNull + Handler handler; public ContactListPresenter(ContactRepository contactRepository) { this.contactRepository = contactRepository; + handler = new Handler(Looper.getMainLooper()); } public void requestContactList() { @@ -25,13 +31,12 @@ public void requestContactList() { } @Override - public void onDestroy() { - this.contactRepository = null; - super.onDestroy(); - } - - @Override - public void getPersonList(List personList) { - getViewState().getContactList(personList); + public void getPersonList(final List personList) { + handler.post(new Runnable() { + @Override + public void run() { + getViewState().getContactList(personList); + } + }); } } diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactDetailsFragment.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactDetailsFragment.java index f676991..a34b355 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactDetailsFragment.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactDetailsFragment.java @@ -226,32 +226,22 @@ private boolean checkBirthdayReminder() { @Override public void getContactDetails(PersonModelAdvanced personModel) { this.person = personModel; - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - if (person != null) { - Log.d(LOG_TAG, "Создаем список контактных данных контакта " + person.getFullName()); - updateFields(); - } else { - Log.e(LOG_TAG, "onFetchPersonModel - репозиторий вернул personModels=null"); - } - } - }); + if (person != null) { + Log.d(LOG_TAG, "Создаем список контактных данных контакта " + person.getFullName()); + updateFields(); + } else { + Log.e(LOG_TAG, "onFetchPersonModel - репозиторий вернул personModels=null"); + } } @Override public void getContactsInfo(List listOfContacts) { this.contactInfoList = listOfContacts; - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - if (lvContacts != null && contactInfoList != null) { - ContactListAdapter contactListAdapter = new ContactListAdapter(getContext(), contactInfoList); - lvContacts.setAdapter(contactListAdapter); - } else { - Log.e(LOG_TAG, "onFetchContacts - репозиторий вернул contactInfoList=null"); - } - } - }); + if (lvContacts != null && contactInfoList != null) { + ContactListAdapter contactListAdapter = new ContactListAdapter(getContext(), contactInfoList); + lvContacts.setAdapter(contactListAdapter); + } else { + Log.e(LOG_TAG, "onFetchContacts - репозиторий вернул contactInfoList=null"); + } } } diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactListFragment.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactListFragment.java index 0fbd98e..24751c7 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactListFragment.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/ui/fragments/ContactListFragment.java @@ -124,16 +124,11 @@ public void onDestroyView() { @Override public void getContactList(final List personList) { - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - if (personList != null && listviewPersons != null) { - Log.d(LOG_TAG, "Создаем список контактов " + personList.size()); - personListAdapter = new PersonListAdapter(getActivity(), personList); - listviewPersons.setAdapter(personListAdapter); - } - } - }); + if (personList != null && listviewPersons != null) { + Log.d(LOG_TAG, "Создаем список контактов " + personList.size()); + personListAdapter = new PersonListAdapter(getActivity(), personList); + listviewPersons.setAdapter(personListAdapter); + } } } From 3f746820e6a51226fb763ed9471ff1b1aca226d5 Mon Sep 17 00:00:00 2001 From: Mikhail Yukhnin Date: Mon, 15 Jun 2020 16:36:31 +0400 Subject: [PATCH 7/7] =?UTF-8?q?=D0=94=D0=BE=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8?= =?UTF-8?q?=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5=20=D0=B8=D1=81=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yuhnin/lesson1/presenters/ContactDetailsPresenter.java | 6 +++--- .../yuhnin/lesson1/presenters/ContactListPresenter.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java index a3754c4..e8eb63a 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java @@ -18,11 +18,11 @@ @InjectViewState public class ContactDetailsPresenter extends MvpPresenter implements PersonDetailsCallback { @NonNull - ContactRepository contactRepository; + private final ContactRepository contactRepository; @NonNull - Handler handler; + private final Handler handler; - public ContactDetailsPresenter(ContactRepository contactRepository) { + public ContactDetailsPresenter(@NonNull ContactRepository contactRepository) { this.contactRepository = contactRepository; this.handler = new Handler(Looper.getMainLooper()); } diff --git a/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java index 68b1f0b..b911488 100644 --- a/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java +++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java @@ -17,11 +17,11 @@ @InjectViewState public class ContactListPresenter extends MvpPresenter implements PersonListCallback { @NonNull - ContactRepository contactRepository; + private final ContactRepository contactRepository; @NonNull - Handler handler; + private final Handler handler; - public ContactListPresenter(ContactRepository contactRepository) { + public ContactListPresenter(@NonNull ContactRepository contactRepository) { this.contactRepository = contactRepository; handler = new Handler(Looper.getMainLooper()); }