• Есть ли нативная ORM для Android?

    artemgapchenko
    @artemgapchenko
    И не появилось ли для андройда нормального NoSQL хранилища, типа MongoDB?

    Понятие "нормальность" может варьироваться, но в голову сразу приходят Realm и ObjectBox.
    Ответ написан
    Комментировать
  • Как создать кнопку возврата в ActionBar'е?

    artemgapchenko
    @artemgapchenko
    Вешайте обработчик нажатия на item с id android.R.id.home.
    Есть ещё вариант не обработчик вешать, а указать в манифесте родительскую активность - тогда при нажатии на up кнопку у вас будет происходить возврат на родительскую активити безо всякого дополнительного кода.
    Ответ написан
    Комментировать
  • Возможно ли сменить тариф Payoneer с базового на предлагаемый тариф с Upwork?

    artemgapchenko
    @artemgapchenko
    Есть возможность, сам год назад менял. Вам просто вышлют новую ко-брендовую карту (Payoneer-Upwork), как дойдет - активируете её и всё. Старая карта заблокируется, все средства с неё переведутся на новую.
    Ответ написан
    Комментировать
  • Как прокачать навык разработки архитектуры информационной системы?

    artemgapchenko
    @artemgapchenko
    Чтение (Роберт Мартин aka Uncle Bob, Майкл Физерс, Стив Макконнелл, Банда Четырех и так далее), изучение чужого кода и практика. Только так. Можете начать с изучения аббревиатуры SOLID (всё тот же Мартин, книга называется "Быстрая разработка программ. Принципы, примеры, практика") и выбирать литературу дальше, основываясь на сносках в Мартине.

    Хотя, если вы на совсем начальном уровне (что подразумевает ваш вопрос), то вам бы в хороший офис года на полтора-два - там привьют начальные представления о хорошем и плохом, заложат фундамент правильных привычек, а дальше можно уже и за литературу браться, как усвоите основы и набьёте свои шишки.
    Ответ написан
    Комментировать
  • Какую литературу почитать по проектированию?

    artemgapchenko
    @artemgapchenko
    "Agile Software Development: Principles, Patterns, and Practices" Роберта Мартина. И "Чистый Код" за его же авторством.
    Ответ написан
    Комментировать
  • Немного о правильности написания кода. Какой вариант выбрать?

    artemgapchenko
    @artemgapchenko
    Много уровней вложенности плохо читаются. Попробуйте добавить внутрь условия

    if (rulesField.isChecked()) {
        register(numberField.getText().toString(), codeField.getText().toString());
    }

    Ещё парочку вложенных if-else, чтобы получилось вот такое:

    @Override
        public void onButtonClick() {
            if (isRequested()) {
                if (rulesField.isChecked()) {
                        if (canProceed()) {
                             register(numberField.getText().toString(), codeField.getText().toString());
                        } else if (isExtraRequestRequired()) {
                            doSomething();
                         } else if (oneMoreCondition()) {
                             doSmomethingOnExtraCondition();
                         } else {
                              Log.e("Unexpected condition");
                         }
                } else {
                    showMessage(R.string.error_rules);
                }
            } else {
                requestRegister(numberField.getText().toString());
            }
        }

    и вы поймёте, что удерживать в голове ту ветку, которая вам интересна (сначала if, потом вложенный в него else, потом второй if-else из вложенных в else первого if'а) становится решительно невозможно. Поэтому и стараются так структурировать код, чтобы он был "плоским", то есть без вложенности. Это, конечно идеал, и иногда труднодостижимый, но стремиться к нему стоит - человек, который после вас будет читать ваш листинг (а чаще всего это будете вы сами недели через две после того, как вы его написали, и успешно забыли всю структуру), скажет вам спасибо.
    Ответ написан
    2 комментария
  • Как посмотреть данные в sqlite на эмуляторе андроид?

    artemgapchenko
    @artemgapchenko
    Подключите Stetho и смотрите через него.
    Ответ написан
    Комментировать
  • Изменить дату Calendar в андроиде?

    artemgapchenko
    @artemgapchenko
    calendar.add(Calendar.DAY_OF_YEAR, 10);
    forDate.setText(calendar.getTime());
    Ответ написан
  • Кто должен логировать? Функция или тот, кто её вызывает?

    artemgapchenko
    @artemgapchenko
    То, что вы описали, называется в англоязычной литературе cross-cutting concerns - это такие области кода, которые решают не саму бизнес-задачу, а являются как бы перпендикулярными к ней, и относятся скорее к функционированию системы. Вы правы насчёт того, что добавлять логирование в саму функцию - это, наверное, не совсем правильный выбор, так как во-первых, функция начинает решать две задачи, что сразу же уменьшает время на понимание её работы, а во-вторых, возможно будут варианты вызова функции, при которых её выполнение логировать не обязательно.
    Я бы, возможно, попробовал зайти к этой задаче со стороны паттерна Декоратор (дальше пишу на Java, так как этот язык для меня основной, но принципы должны быть понятны).

    Определяем интерфейс:

    interface ClientHandler {
    	void blockUser(User user);
    	void unblockUser(User user);
    }

    Дальше пишем реализацию, которая будет заниматься блокированием/разблокированием пользователя:

    public final class ClientHandlerImpl implements ClientHandler {
    	public void blockUser(User user) {
    		// Логика блокирования пользователя
    	}
    
    	public void unblockUser(User user) {
    		// Логика разблокирования пользователя
    	}
    }

    А теперь ход конём: пишем декоратор, который будет оборачивать собой написанную нами имплементацию (и в аргументе конструктора пробрасываем ClientHandlerImpl):

    public final class ClientHandlerLoggingDecorator implements ClientHandler {
    	private final ClientHandler handler;
    
    	public ClientHandlerLoggingDecorator(final ClientHandler handler) {
    		this.handler = handler;
    	}
    
    	public void blockUser(User user) {
    		Log.d("User " + user.getName() + " blocked!")
    		handler.blockUser(user);
    	}
    
    	public void unblockUser(User user) {
    		Log.d("User " + user.getName() + " unblocked!")
    		handler.unblockUser(user);
    	}
    }


    Дальше можно будет создать, например, фабрику ClientHandler'ов, которая по запросу будет возвращать нам новый инстанс ClientHandler'а:

    public final class ClientHandlerFactory {
    	public static ClientHandler getClientHandler() {
    		return new ClientHandlerLoggingDecorator(new ClientHandler());
    	}
    }

    Чего мы добились:
    1. Код логирования вынесен из реализации ClientHandler, если вам нужно будет изучить реализацию блокирования/разблокирования, вы просто открываете ClientHandlerImpl, и изучаете её.
    2. (связано с предыдущим пунктом) Реализацию блокирования/разблокирования и логирования теперь можно менять независимо друг от друга.
    3. Логирующее поведение становится скрытым для пользователей ClientHandler - они просто получают новый инстанс при обращении к фабрике, и используют его. Хотите отключить логирование? Меняете реализацию фабрики, и она начинает возвращать ClientHandlerImpl. Хотите сделать это поведение настраиваемым? Пишете дополнительный код, который на старте читает конфигурацию, и начинает использовать либо ту реализацию фабрики, которая возвращает ClientHandler, покрытый декоратором, либо реализацию, которая возвращает голый ClientHandler. Либо же зашиваете этот выбор внутрь самой фабрики.
    Ответ написан
    Комментировать
  • Как наиболее кратко и понятно передать в один аргумент функции одну из двух переменных, которые могут быть либо массивом, либо логическим выражением?

    artemgapchenko
    @artemgapchenko
    Возможно вы неправильно подходите к самой задаче. Я бы избавился вообще от функции, которая по понедельникам принимает boolean, по вторникам - массив, а по остальным дням недели - объект, так как эта функция берёт на себя слишком много ответственности, и перешёл бы вместо неё к трем разным функциям, первая из которых принимает в качестве аргумента boolean, вторая - массив, а третья - объект.
    Код пишется не только для выполнения, но и для чтения другими разработчиками, и подобная функция явно не способствует скорости изучения кода и внесения в него изменений.
    Ответ написан
    2 комментария
  • Как конфигурировать параметры приложения в зависимости от типа build'a?

    artemgapchenko
    @artemgapchenko
    Привет.

    для debug билда url API должен указывать на локальную виртуалку, для release - url указывает на продакшн-сервер

    Тут лучше всего подойдут т.н. build config fields. Описываете его в build.gradle файле, а потом используете его как BuildConfig.API_URL. Пример здесь.

    для debug билда отключен Crash Reporting, для release - репорт ошибок включен

    Просто инициализируете свой крэш репортинг через if вот так:
    if (!BuildConfig.DEBUG) {
        // инициализируем
    }

    В идеале хотлесь бы еще конфигурировать классы (например в debug вместо AnalyticTracker использовать AnalyticTrackerStub).

    Для разных билд типов можно задавать свои наборы исходников. На том же уровне, на котором находится главный набор исходников (main), определите ещё пару наборов - debug и release. Внутри них и размещаете свой AnalyticTracker: debug/java/com/myapp/utils/AnalyticTracker.java и release/java/com/myapp/utils/AnalyticTracker.java. В зависимости от того, какой у вас сейчас выбран build variant (debug или release), Android Studio будет использовать или первую или вторую версию класса AnalyticTracker. Да, из главного набора исходников AnalyticTracker.java нужно будет удалить, иначе Android Studio не сумеет выбрать нужный класс. Более подробная документация тут.
    Ответ написан
    1 комментарий
  • Как получить размер ImageView?

    artemgapchenko
    @artemgapchenko
    ViewTreeObserver даёт возможность подцепиться к определённым этапам в "жизненном цикле" View, в том числе к этапу, когда размеры View были определены:

    imageview.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            //
            // Тут вы пишите ваш код, который завязан на знание размера View
            //
    
            // А тут отсоединяете OnGlobalLayoutListener
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                imageview.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            } else {
                imageview.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
        } 
    });
    Ответ написан
    2 комментария
  • Как правильно сделать клик по item?

    artemgapchenko
    @artemgapchenko
    Добавьте следующее к корневому ViewGroup вашего item'a:
    android:descendantFocusability="blocksDescendants"
    Ответ написан
    Комментировать
  • Как в одном активити использовать android.support.v4.app.Fragment и android.app.Fragment?

    artemgapchenko
    @artemgapchenko
    Нельзя.
    AppCompatActivity порождает FragmentManager из support библиотеки, который, в свою очередь, умеет работать только с Fragment из support библиотеки.
    Обычный Activity порождает FragmentManager из SDK, который, в свою очередь, умеет работать только с Fragment из SDK.
    Ответ написан
    Комментировать
  • Refund удаляет работу из профиля?

    artemgapchenko
    @artemgapchenko
    Да, после возврата средств работа удалится из профиля, то есть в списке выполненных вами контрактов, который есть в вашем профиле, показываться она не будет. Но ваш Job Success Score все равно упадет, и точной причины я не знаю - либо он упадет из-за самого факта возврата средств, либо скрытый отзыв, который оставляет клиент (там, где он оценивает вас по шкале от 1 до 10 в плане того, рекомендовал бы он вас как исполнителя другим клиентам) вносит свои коррективы.
    Вообще многие советуют в своем отзыве подробно описывать почему заказчик неадекват, и средства сохранять, если там приличная сумма: во-первых чтобы он не привыкал к мысли, что можно и работу получить, и денег не заплатить, а во-вторых это ваши деньги всё-таки.
    Ответ написан
    9 комментариев
  • Обнуляет ли UpWork количество полученных средств с началом календарного года?

    artemgapchenko
    @artemgapchenko Автор вопроса
    Окей, в общем информация оказалась неактуальной, Certificate of Earnings всегда показывает объём средств, заработанных за последние 12 месяцев, а не за полгода.
    Ответ написан
    Комментировать
  • Зачем нужен Dependency Injection в Android разработке?

    artemgapchenko
    @artemgapchenko
    Начать неплохо бы с понимания того, что такое DI. Обратимся к википедии:

    Внедрение зависимости (англ. Dependency injection, DI) — процесс предоставления внешней зависимости программному компоненту.

    Если выражаться не канцеляритом, а обычным русским языком, то DI - это когда вы своему компоненту (например, классу) предоставляете нужные для него зависимости извне, а не создаете их сами в конструкторе, или через инициализацию в месте объявления поля. То есть не так:

    public class Api {
    	....
    	private final HttpClient client = new OkClient();
    }

    А, например, так:

    public class Api {
    	....
    	private final HttpClient client;
    
    	public Api(@NonNull HttpClient client) {
    		this.client = client;
    	}
    }


    И что нам это даёт?

    Ну, очевидно, нам теперь проще менять зависимости. Нужна вам другая реализация абстрактного класса HttpClient - взяли, и передали её через конструктор, или через метод-setter. В случае с первым куском кода, вам пришлось бы ещё и класс Api переписывать, что в случаях, отличных от тривиальных, может привести к ошибкам. Получается, что ваш класс теперь закрыт от изменений (смотрим Open/Closed Principle).

    Окей, а на практике-то какие бенефиты?

    Во-первых, вы теперь можете написать инициализацию вашей программы через конфигурационные файлы. Скажем, на старте будет читаться простенький текстовый файл, который определяет, какой httpclient использовать, какие настройки доступа к бд применять и так далее, и, исходя из этого, будут определяться зависимости.
    Во-вторых, вам теперь существенно проще писать тесты. Написали вы, скажем, какой-нибудь парсер, который принимает InputStream, содержащий в себе данные json-объекта, как-то хитро его парсит, и выдаёт вам объект вашей бизнес-модели. В приложении этот парсер будет принимать на вход реализацию InputStream'а, которая берёт данные из сети, а в тестах - реализацию, которая просто читает файл с диска (потому что тесты должны выполняться часто и быстро, и ваша задача в тесте - протестировать ваш парсер, а не скорость сетевого соединения).

    Вот, в общем-то, и всё. А Dagger - это просто библиотека, которая автоматизирует ручное внедрение зависимостей, равно как и другие DI-библиотеки.

    P.S. В некоторых случаях чрезмерное увлечение DI может привести к нежелательным эффектам, вроде чрезмерного усложнения кода, поэтому внедряйте аккуратно. Понимание приходит с опытом.
    Ответ написан
    Комментировать
  • Не возвращается список файлов на карте памяти?

    artemgapchenko
    @artemgapchenko
    Наверняка на Android 6 запускаете. Разрешения, начиная с этой версии, должны запрашиваться на стадии выполнения. Вот вам статейка для изучения.
    Ответ написан
  • Как предотвратить случайный pull-to-refresh при скроллинге вниз?

    artemgapchenko
    @artemgapchenko
    внутри ScrollView есть RecyclerView.
    Зачем? RecyclerView/ListView/GridView не предназначены для того, чтобы их внутрь ScrollView засовывать, у вас из-за этого всё переиспользование дочерних виджетов к чертям летит. Начните с исправления этой проблемы, а потом беритесь за траблу с pull-to-refresh (хотя вангую, что она после исправления первой проблемы исчезнет).
    Ответ написан
    2 комментария
  • Стоит ли продолжать изучать Android develop?

    artemgapchenko
    @artemgapchenko
    Здравствуйте, как многие знают, Google готовит замену Android

    Откуда вы всё это берёте? Есть проект на Гитхабе с таким вот README:

    Pink + Purple == Fuchsia (a new Operating System)

    Всё. Ни про замену Android, ни про предназначение проекта ничего не сказано. К проекту подключено 3 (три) человека, развивается он без году неделя, никаких официальных анонсов не было.
    Прекращайте читать советские газеты перед обедом и вместо первоисточников и не занимайтесь домыслами того, чего нет. Изучайте Android и выбросите Фуксию из головы на ближайшие года два, пока не станет понятно, что это такое и кому это нужно.
    Ответ написан
    Комментировать