Повсеместный @Expose, передёргивание списков
Меня никогда не тыкали носом в мои ошибки в коде, потому что я его никому не показывал, очень хочу узнать свои слабые стороны.
Алексей
Возможные ошибки
- Потенциально этот метод может быть использован для создания нескольких HTTP-клиентов, у которых общий кэш. Они могут мешать друг другу.
- Picasso позволяется иметь кэш размером в 2 ГБ: new OkHttp3Downloader(context, Integer.MAX_VALUE);. Если не знаешь, сколько хочешь выделить под кэш, предел можно не указывать.
Бессмысленные действия
public static void fetchStatusList(final OnDownloadListener downloadCompleteListener){
if(!NetworkStatusChecker.isNetworkAvalible(DataManager.getInstance().getContext())){
downloadCompleteListener.onDownloadFailed("Загрузка невозможно, проверьте интернет соединение");
}
String searchTag = DataManager.getInstance().getPreferencesManager().getSearchTag();
if(searchTag.equals("")|| searchTag.isEmpty()){
fetchRecentPublic(downloadCompleteListener);
}else {
fetchStatusesByTeg(downloadCompleteListener, searchTag);
}
}
- Если интернет недоступен, fetch* всё равно будет вызван.
- searchTag.isEmpty() покрывает случай с searchTag.equals("").
@SerializedName("id")
@Expose
private String id;
@SerializedName("created_at")
@Expose
private String createdAt;
@SerializedName("in_reply_to_id")
@Expose
private Object inReplyToId;
@SerializedName("in_reply_to_account_id")
@Expose
private Object inReplyToAccountId;
@SerializedName("sensitive")
@Expose
private Boolean sensitive;
...
- Не нужно ставить @Expose повсюду. В JavaDoc к Gson написано, как и зачем ею пользоваться.
- Object — это достаточно бесполезный тип. Если поле не используется, его вообще не должно быть. Если используется — тип должен быть конкретным.
- Не стоит без необходимости использовать boxed primitives, например, Boolean.
public static DataManager getInstance() {
if (INSTANCE == null) {
INSTANCE = new DataManager();
}
return INSTANCE;
}
- Такие синглтоны не потокобезопасны. Если getInstance будет вызван из разных потоков, они могут увидеть разные значения INSTANCE и получить в своё распоряжение разные экземпляры.
- По большому счёту, ленивость здесь не нужна. private static final INSTANCE = new DataManager(); — проще и потокобезопасно. Всё равно экземпляр создастся только при загрузке класса, а она ленивая.
list.clear();
list.addAll(anotherList);
Как бы назвать этот антипаттерн... передёргивание списка. Можно же просто заменить старый новым. Чем меньше объекты изменяешь, тем меньше появляется багов. (Поэтому живут и здравствуют функциональные языки.)
mStatusListAdapter = new StatusListAdapter(mStatusList, this);
mRecyclerView.setAdapter(mStatusListAdapter);
if(mStatusList.size()!=0){
mStatusListAdapter.notifyDataSetChanged();
}else {
StatusListFetcher.fetchStatusList(mDownloadCompleteListener);
}
Нет смысла уведомлять свежесозданный адаптер об изменениях.
Пожалуй, стоит добавить постраничную загрузку и индикатор загрузки в StatusListActivity. Тогда появится много интересной работы: правильно обработать поворот экрана, скрыть полосу при ошибке. Иначе как-то слишком просто.
Именование
- Опять венгерская нотация.
- Нет слова avalible, есть available.
- Нет слова teg.
- ConstantManager — это неуместное название, он ничем не управляет. Вообще, у каждого класса константы должны быть свои. Собирание констант в общий класс провоцирует лишнее связывание.
Отступы
- Всегда удивляли такие отступы. Неужели не мешает читать код? Такого в проекте очень много. Рекомендую попросить IDE отформатировать весь код и впредь соблюдать все отступы.
Обработка ошибок
if(response.isSuccessful()) {. А если нет?
Строки
Кучу раз говорил, строки должны быть в ресурсах.
Загрузка невозможно, проверьте интернет соединение. Загрузка женского рода, она невозможна. Интернет-соединение пишется через дефис.