От переводчика: перевод делался сходу, за один присест, так что в некоторых местах может быть немного топорным. В любом случае, вы знаете, куда писать об ошибках.
В комментариях к оригинальной статье есть несколько здравых мыслей, как, например, не использовать библиотеки с мира «большой» джавы, так как они слишком объемные, или использовать всякие Glide-ы вместо Picasso (с чем я, впрочем, согласен). Можете посмотреть, если интересно.
И еще, я не придумал, как заставить отображаться сниппеты с гитхаба, так что я просто скопировал код.
Мое первое приложение было ужасным. В самом деле, оно было настолько кошмарным, что я удалил его с маркета и больше даже не буду указывать его в своем резюме. То приложение могло быть не настолько ужасным, если бы я знал несколько вещей об Android-разработке перед его написанием.
Далее следует список вещей, которые надо понимать во время разработки вашего первого приложения под Android. Эти уроки были извлечены из реальных ошибок, которые я делал в исходном коде моей первой программы, — ошибкок, которые я буду приводить ниже. Понимание этих вещей поможет вам написать приложение, которым вы будете гордиться чуть больше.
Конечно, если вы пишете что-то по ходу изучения Android-разработки, скорее всего, позже вы все равно возненавидите свое творение. Как сказал @codestandards:
(Если код, который вы написали год назад, не кажется вам плохим, вы, наверное, недостаточно учились)
Если вы — опытный Java-разработчик, пункты 1, 2 и 5 могут быть вам неинтересны. С другой стороны, пункты 3 и 4 могут показать вам некоторые крутые штуки, которые можно делать с Android Studio, о которых вы не слышали, даже если и не делали ошибок, приведенных в примерах для этих пунктов.
Это может выглядеть как ошибка, которую никто бы не додумался сделать. Это не так. Я додумался. Я видел людей, которые совершали эту же ошибку, и я собеседовал людей, которые не могли сходу объяснить, почему это серьезная ошибка. Не делайте так. Это по-нубски.
Если MeTrackerStore сохраняет ссылку на Activity, переданную в конструктор, эта Activity никогда не будет уничтожена сборщиком мусора (пока эта статическая ссылка не будет переназначена другой Activity). Это потому что mMeTrackerStore — статическая, и память для статических переменных не высвобождается, пока не завершится процесс, в котором запущено приложение. Если у вас возникает соблазн сделать так, видимо, что-то серьезно не так с вашим кодом. Ищите помощи. Может быть, вам поможет курс от Google на Udacity: "Android Development for Beginners".
Примечание: технически, вы можете хранить ссылку на контекст приложения без возникновения утечки памяти, но я все равно не рекомендую вам делать это.
С этим кодом несколько проблем. Я сосредоточусь на одной. В Java (нестатические) внутренние классы имеют неявную ссылку на экземпляр класса, который их содержит.
В этом примере у любого GetLatAndLongAndUpdateMapCameraAsyncTask была бы ссылка на DefineGeofenceFragment, который его содержит. То же верно и в отношении анонимных классов.
У GetLatAndLongAndUpdateMapCameraAsyncTask есть неявная ссылка на фрагмент, объект, чем жизненный цикл мы не контролируем. Ответственность за создание и уничтожение фрагментов лежит на Android SDK, и если GetLatAndLongAndUpdateCameraAsyncTask не может быть почищен сборщиком, потому что по-прежнему выполняется, его неявная ссылка на DefineGeofenceFragment попрепятствует сборщику удалить и фрагмент.
Вот отличное видео с Google I/O, где объясняется, почему подобные вещи происходят.
Этот сниппет содержит то, что получается при использовании «Generate Getter» в Android Studio. Геттер оставляет префикс «m» в имени сгенерированного метода. Это не лучший вариант.
(Если вас больше волнует, почему к переменной экземпляра добавляют префикс «m»: «m» часто добавляется согласно code-convention. Расшифровывается как «member»)
Независимо от того, считаете ли вы добавление префикса хорошей идеей, стоит знать, что Android Studio позволяет писать код в соответствии с любой конвенцией, который вы следуете. К примеру, вы можете использовать настройки code style, чтобы указать Android Studio автоматически добавлять префикс вашим переменным экземпляра и удалять его при генерации геттеров, сеттеров и параметров конструктора.
Вообще, Android Studio умеет намного больше. Изучение шорткатов и шаблонов — это то, с чего можно начать.
В одном из написанных мною классов был метод длиной более 100 строк. Такие методы сложны для чтения, изменения и переиспользования. Попробуйте писать методы, делающие всего одну вещь. Как правило, под подозрение должны попадать все методы длиной более 20 строк. В поиске таких методов можно попросить помощи у Android Studio.
Может звучать тривиально, но эту ошибку я совершил при написании первого приложения.
Когда вы создаете программы, вы будете ошибаться. Другие люди уже совершали эти ошибки. Учитесь у этих людей. Повторяя решенные другими проблемы, вы тратите свое время. Я потратил кучу времени на мое первое приложение, делая ошибки, которые я мог бы избежать, если бы просто потратил немного больше времени на обучение от опытных разработчиков.
Прочитайте Pragmatic Programmer. Потом Effective Java. Эти две книги помогут вам избежать основные ошибки, которые делают новички. Покончив с этими книгами, продолжайте искать умных людей, у которых можно поучиться.
Когда вы пишете свое приложение, вы, вероятно, столкнетесь с проблемами, которые более умные и опытные люди уже решили. Более того, многие из этих решений доступны в виде библиотек с открытым кодом. Воспользуйтесь ими.
В своем первом приложении я писал код, который обеспечивал функциональность, уже предоставляемую библиотеками. Некоторые из библиотек были стандартными. Другие — сторонними, вроде Retrofit и Picasso. Если вы не уверены, какими библиотеками стоит воспользоваться, вам следует сделать следующих три вещи:
Написание хороших Android-программ может быть очень сложным. Не усложняйте себе жизнь еще больше повторением моих ошибок. Если вы нашли ошибку в том, что я написал, сообщите об этом в комментариях (ошибочные комментарии не хуже их отсутствия). Если вы думаете, что это будет полезным для какого-то новичка, поделитесь статьей с ним. Спасите их от некоторой головной боли.
В комментариях к оригинальной статье есть несколько здравых мыслей, как, например, не использовать библиотеки с мира «большой» джавы, так как они слишком объемные, или использовать всякие Glide-ы вместо Picasso (с чем я, впрочем, согласен). Можете посмотреть, если интересно.
И еще, я не придумал, как заставить отображаться сниппеты с гитхаба, так что я просто скопировал код.
Мое первое приложение было ужасным. В самом деле, оно было настолько кошмарным, что я удалил его с маркета и больше даже не буду указывать его в своем резюме. То приложение могло быть не настолько ужасным, если бы я знал несколько вещей об Android-разработке перед его написанием.
Далее следует список вещей, которые надо понимать во время разработки вашего первого приложения под Android. Эти уроки были извлечены из реальных ошибок, которые я делал в исходном коде моей первой программы, — ошибкок, которые я буду приводить ниже. Понимание этих вещей поможет вам написать приложение, которым вы будете гордиться чуть больше.
Конечно, если вы пишете что-то по ходу изучения Android-разработки, скорее всего, позже вы все равно возненавидите свое творение. Как сказал @codestandards:
If the code you wrote a year ago doesn't seem bad to you, you're probably not learning enough.— Code Standards ( @codestandards) 21 мая 2015
(Если код, который вы написали год назад, не кажется вам плохим, вы, наверное, недостаточно учились)
Если вы — опытный Java-разработчик, пункты 1, 2 и 5 могут быть вам неинтересны. С другой стороны, пункты 3 и 4 могут показать вам некоторые крутые штуки, которые можно делать с Android Studio, о которых вы не слышали, даже если и не делали ошибок, приведенных в примерах для этих пунктов.
1. Не создавайте статических ссылок на контекст
public class MainActivity extends LocationManagingActivity implements ActionBar.OnNavigationListener,
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener {
//...
private static MeTrackerStore mMeTrackerStore;
//...
@Override
protected void onCreate(Bundle savedInstanceState) {
//...
mMeTrackerStore = new MeTrackerStore(this);
}
}
Это может выглядеть как ошибка, которую никто бы не додумался сделать. Это не так. Я додумался. Я видел людей, которые совершали эту же ошибку, и я собеседовал людей, которые не могли сходу объяснить, почему это серьезная ошибка. Не делайте так. Это по-нубски.
Если MeTrackerStore сохраняет ссылку на Activity, переданную в конструктор, эта Activity никогда не будет уничтожена сборщиком мусора (пока эта статическая ссылка не будет переназначена другой Activity). Это потому что mMeTrackerStore — статическая, и память для статических переменных не высвобождается, пока не завершится процесс, в котором запущено приложение. Если у вас возникает соблазн сделать так, видимо, что-то серьезно не так с вашим кодом. Ищите помощи. Может быть, вам поможет курс от Google на Udacity: "Android Development for Beginners".
Примечание: технически, вы можете хранить ссылку на контекст приложения без возникновения утечки памяти, но я все равно не рекомендую вам делать это.
2. Остерегайтесь «неявных ссылок» на объекты, чей жизненный цикл вы не контролируете
public class DefineGeofenceFragment extends Fragment {
public class GetLatAndLongAndUpdateMapCameraAsyncTask extends AsyncTask<String, Void, LatLng> {
@Override
protected LatLng doInBackground(String... params) {
//...
try {
//Here we make the http request for the place search suggestions
httpResponse = httpClient.execute(httpPost);
HttpEntity entity = httpResponse.getEntity();
inputStream = entity.getContent();
//..
}
}
}
}
С этим кодом несколько проблем. Я сосредоточусь на одной. В Java (нестатические) внутренние классы имеют неявную ссылку на экземпляр класса, который их содержит.
В этом примере у любого GetLatAndLongAndUpdateMapCameraAsyncTask была бы ссылка на DefineGeofenceFragment, который его содержит. То же верно и в отношении анонимных классов.
У GetLatAndLongAndUpdateMapCameraAsyncTask есть неявная ссылка на фрагмент, объект, чем жизненный цикл мы не контролируем. Ответственность за создание и уничтожение фрагментов лежит на Android SDK, и если GetLatAndLongAndUpdateCameraAsyncTask не может быть почищен сборщиком, потому что по-прежнему выполняется, его неявная ссылка на DefineGeofenceFragment попрепятствует сборщику удалить и фрагмент.
Вот отличное видео с Google I/O, где объясняется, почему подобные вещи происходят.
3. Сделайте так, чтобы Android Studio работала на вас
public ViewPager getmViewPager() {
return mViewPager;
}
Этот сниппет содержит то, что получается при использовании «Generate Getter» в Android Studio. Геттер оставляет префикс «m» в имени сгенерированного метода. Это не лучший вариант.
(Если вас больше волнует, почему к переменной экземпляра добавляют префикс «m»: «m» часто добавляется согласно code-convention. Расшифровывается как «member»)
Независимо от того, считаете ли вы добавление префикса хорошей идеей, стоит знать, что Android Studio позволяет писать код в соответствии с любой конвенцией, который вы следуете. К примеру, вы можете использовать настройки code style, чтобы указать Android Studio автоматически добавлять префикс вашим переменным экземпляра и удалять его при генерации геттеров, сеттеров и параметров конструктора.
Вообще, Android Studio умеет намного больше. Изучение шорткатов и шаблонов — это то, с чего можно начать.
4. Методы должны делать одну вещь
В одном из написанных мною классов был метод длиной более 100 строк. Такие методы сложны для чтения, изменения и переиспользования. Попробуйте писать методы, делающие всего одну вещь. Как правило, под подозрение должны попадать все методы длиной более 20 строк. В поиске таких методов можно попросить помощи у Android Studio.
5. Учитесь у людей, которые умнее и опытнее вас
Может звучать тривиально, но эту ошибку я совершил при написании первого приложения.
Когда вы создаете программы, вы будете ошибаться. Другие люди уже совершали эти ошибки. Учитесь у этих людей. Повторяя решенные другими проблемы, вы тратите свое время. Я потратил кучу времени на мое первое приложение, делая ошибки, которые я мог бы избежать, если бы просто потратил немного больше времени на обучение от опытных разработчиков.
Прочитайте Pragmatic Programmer. Потом Effective Java. Эти две книги помогут вам избежать основные ошибки, которые делают новички. Покончив с этими книгами, продолжайте искать умных людей, у которых можно поучиться.
6. Используйте библиотеки
Когда вы пишете свое приложение, вы, вероятно, столкнетесь с проблемами, которые более умные и опытные люди уже решили. Более того, многие из этих решений доступны в виде библиотек с открытым кодом. Воспользуйтесь ими.
В своем первом приложении я писал код, который обеспечивал функциональность, уже предоставляемую библиотеками. Некоторые из библиотек были стандартными. Другие — сторонними, вроде Retrofit и Picasso. Если вы не уверены, какими библиотеками стоит воспользоваться, вам следует сделать следующих три вещи:
- Послушайте серию подкаста Google I/O Fragmented. В этой серии разработчиков спрашивают, какие сторонние библиотеки они считают важными при разработке под Android. Спойлер: В основном это Dagger, Retrofit, Picasso, и Mockito.
- Подпишитесь на Android Weekly. У них есть раздел, содержащий последние появившиеся библиотеки. Следите за ним, там можно найти что-то полезное.
- Ищите приложения с открытым кодом, которые решают проблемы, схожие с теми, с которыми вы сталкиваетесь в своем приложении. Там можно увидеть, что разработчик воспользовался сторонней библиотекой, которую вы не нашли, либо стандартной Java-библиотекой, о которой вы не знали.
Заключение
Написание хороших Android-программ может быть очень сложным. Не усложняйте себе жизнь еще больше повторением моих ошибок. Если вы нашли ошибку в том, что я написал, сообщите об этом в комментариях (ошибочные комментарии не хуже их отсутствия). Если вы думаете, что это будет полезным для какого-то новичка, поделитесь статьей с ним. Спасите их от некоторой головной боли.
stepanp
Очередная говностатья с пережевыванием банальных вещей надерганных из интернета. Дальше второго пункта можно не читать.
Нафига вообще такое переводить?
Bringoff Автор
У вас есть варианты лучше? Предлагайте.
А хотя не надо, у меня в pocket не одна интересная статья пылится, хоть бы к ним добраться. Сами лучше переведите.
stepanp
Сперва добейся
slonopotamus
Вам предъявляют претензию не к тому, КАК вы перевели, а к тому, ЧТО вы перевели. Слегка андроидо-специфичен только второй пункт, первый — обычное рукожопие (увеличение scope'а ссылки на объект за пределы lifecycle'а объекта), а остальные — банальщина. В общем, текст, не стоящий хоть сколько-нибудь большого внимания.
Bringoff Автор
Я заметил, к чему он предъявил претензию. И говорю, что перевел то, что понравилось мне. Переведите то, что понравилось вам, я с удовольствием почитаю.
Еще раз — у меня сохранено достаточно «небанальщины», но руки к ней не доходят.