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 7a8bfa5..207fa95 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -25,11 +25,16 @@ 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.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);
+}
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/ContactDetailsPresenter.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java
new file mode 100644
index 0000000..e8eb63a
--- /dev/null
+++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactDetailsPresenter.java
@@ -0,0 +1,58 @@
+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;
+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.InjectViewState;
+import com.arellomobile.mvp.MvpPresenter;
+
+import java.util.List;
+
+@InjectViewState
+public class ContactDetailsPresenter extends MvpPresenter implements PersonDetailsCallback {
+ @NonNull
+ private final ContactRepository contactRepository;
+ @NonNull
+ private final Handler handler;
+
+ public ContactDetailsPresenter(@NonNull ContactRepository contactRepository) {
+ this.contactRepository = contactRepository;
+ this.handler = new Handler(Looper.getMainLooper());
+ }
+
+ public void requestContactsByPerson(String personId) {
+ contactRepository.getContactByPerson(this, personId);
+ }
+
+ public void requestPersonDetails(String personId) {
+ contactRepository.getPersonById(this, personId);
+ }
+
+ @Override
+ public void onFetchPersonDetails(final PersonModelAdvanced personModel) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ getViewState().getContactDetails(personModel);
+ }
+ });
+ }
+
+ @Override
+ 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
new file mode 100644
index 0000000..b911488
--- /dev/null
+++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/presenters/ContactListPresenter.java
@@ -0,0 +1,42 @@
+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;
+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 {
+ @NonNull
+ private final ContactRepository contactRepository;
+ @NonNull
+ private final Handler handler;
+
+ public ContactListPresenter(@NonNull ContactRepository contactRepository) {
+ this.contactRepository = contactRepository;
+ handler = new Handler(Looper.getMainLooper());
+ }
+
+ public void requestContactList() {
+ contactRepository.getAllPersons(this);
+ }
+
+ @Override
+ 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/repository/ContactRepository.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/repository/ContactRepository.java
index f509bf8..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
@@ -3,19 +3,15 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-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.callbacks.PersonDetailsCallback;
+import com.a65apps.yuhnin.lesson1.callbacks.PersonListCallback;
import java.util.List;
public interface ContactRepository {
- @Nullable
- List getAllPersons();
+ void getAllPersons(PersonListCallback callback);
- @NonNull
- List getContactByPerson(String id);
+ void getContactByPerson(PersonDetailsCallback callback, String id);
- @Nullable
- PersonModelAdvanced getPersonById(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 6a57da7..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
@@ -7,14 +7,16 @@
import android.provider.ContactsContract;
import android.util.Log;
-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;
import com.a65apps.yuhnin.lesson1.pojo.PersonModelCompact;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
@@ -33,94 +35,117 @@ public static synchronized ContactRepositoryFromSystem getInstance(Context conte
return instance;
}
- @Nullable
@Override
- public List getAllPersons() {
- 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());
+ public void getAllPersons (PersonListCallback callback) {
+ final WeakReference weakReference = new WeakReference<>(callback);
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ 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();
}
}
+ PersonListCallback local = weakReference.get();
+ if (local != null) {
+ local.getPersonList(personList);
+ }
}
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- return personList;
+ }).start();
}
- @NonNull
@Override
- public List getContactByPerson(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();
}
@Override
- public PersonModelAdvanced getPersonById(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();
}
/**
@@ -276,5 +301,4 @@ private List getEmailList(String personId, ContentResolver con
}
return emailList;
}
-
}
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..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
@@ -23,7 +23,6 @@
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;
@@ -37,16 +36,12 @@ public class MainActivity extends AppCompatActivity
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..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
@@ -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,34 @@
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;
+
+ ImageView ivAvatar;
+ TextView tvFullname;
+ ListView lvContacts;
+ TextView tvDescription;
+ TextView tvBirthday;
+ ToggleButton toggleBtnRemindBirthday;
@NonNull
PersonModelAdvanced person;
@@ -55,22 +59,19 @@ 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(getActivity().getApplicationContext()));
+ }
public ContactDetailsFragment() {
// Required empty public constructor
@@ -95,12 +96,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 +121,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 +136,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 +164,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 +171,6 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
} else {
Log.d(LOG_TAG, "Toggle uncheked");
}
-
setBirthdayReminderEnabled(isChecked);
}
@@ -276,19 +223,25 @@ 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;
+ 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;
+ 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..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
@@ -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(getActivity().getApplicationContext()));
+ }
+
@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,12 @@ public void onDestroyView() {
}
@Override
- public void onDestroy() {
- if (serviceBound) {
- getActivity().unbindService(mConnection);
- serviceBound = false;
+ public void getContactList(final List personList) {
+ if (personList != null && listviewPersons != null) {
+ Log.d(LOG_TAG, "Создаем список контактов " + personList.size());
+ personListAdapter = new PersonListAdapter(getActivity(), personList);
+ listviewPersons.setAdapter(personListAdapter);
}
- super.onDestroy();
- }
-
- @Override
- public void onFetchPersonList(List personList) {
- Log.d(LOG_TAG, "ПОЛУЧЕНЫ ДАННЫЕ СПИСКА КОНТАКТОВ");
- createPersonsListView(personList);
}
-
- 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/views/ContactDetailsView.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/views/ContactDetailsView.java
new file mode 100644
index 0000000..5b5a429
--- /dev/null
+++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/views/ContactDetailsView.java
@@ -0,0 +1,17 @@
+package com.a65apps.yuhnin.lesson1.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/views/ContactListView.java b/app/src/main/java/com/a65apps/yuhnin/lesson1/views/ContactListView.java
new file mode 100644
index 0000000..77cfb2d
--- /dev/null
+++ b/app/src/main/java/com/a65apps/yuhnin/lesson1/views/ContactListView.java
@@ -0,0 +1,13 @@
+package com.a65apps.yuhnin.lesson1.views;
+
+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);
+}