開發(fā)第一個應用之前你需要知道的六件事
我的***個應用非常糟糕。事實上,它非常的糟糕以致于我從應用市場上刪除它,同時我甚至不在我的簡歷上羅列出它。如果我在開發(fā)之前知道一些Android開發(fā)的事情它就不會糟糕到這步田地。
這列羅列的事情在你開發(fā)***個Android應用的時候需要牢記在大腦中。這些我接下來將展示的實際錯誤來自于我的***個應用程序代碼中。把這些錯誤經驗牢記心頭能夠幫助你開發(fā)一個你可以引以為豪的應用。
當然,正如codestandards所說:“如果你所做的工作和你作為學生開發(fā)的Android應用類似,你很有可能會討厭你的應用”。
如果一年前你寫的代碼對于你來說感覺還不錯,你很大程度上沒有進行足夠的學習。
-Code Standards 2015.5.21
如果你是一位經驗豐富的Java開發(fā)者,第1、2、5條很有可能對你沒有吸引力。另一方面,即使你從來沒有犯過這些例子中的錯誤,第3、4條也可能向你展示一些很酷的事物,你可以利用一款也許你不知道的軟件Android Studio去實現(xiàn)這些事物。
1.不要持有Context的靜態(tài)引用
- 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 通過它的構造函數(shù)保持一個指向Activity的引用,這個Activity將不會被垃圾回收(GC)。(除非靜態(tài)變量被從新分配到不同的Activity)。這是因為mMeTrackerStore 是靜態(tài)變量,而靜態(tài)變量的內存是不會被回收,直到應用程序退出才回收。如果你正在試圖做這樣的事情,你的代碼很有可能有嚴重的錯誤。尋找?guī)椭?,可能看看谷歌的Udacity 課程“Android Development for Beginners”能夠幫助你。
注:從技術上說,你可以對一個Application Context進行靜態(tài)變量引用而不引起內存泄露,但我不建議你這樣做。
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中,(非靜態(tài))內部類有個對外部類實例有個隱式引用。
在這個例子中,任何GetLatAndLongAndUpdateCameraAsyncTask都有一個外部類DefineGeofenceFragment的引用。對于匿名類是同樣的,它們也有一個對包含它們的類的實例的一個隱式引用。
GetLatAndLongAndUpdateCameraAsyncTask對生命周期我們無法控制的Fragment對象有一個隱式引用。Android SDK負責創(chuàng)建和銷毀Fragment,如果GetLatAndLongAndUpdateCameraAsyncTask 因為正在運行而不能被垃圾回收,那么DefineGeofenceFragment 也將因為具有隱式引用而保留不能被垃圾回收。
這里有一個很棒的谷歌視頻,解釋它為什么會發(fā)生這種事情。
3.使用Android Studio進行工作
這段代碼是我使用“Generate Getter”在Android Studio中進行生成的。這些getter保持了’m’前綴的實例變量,同樣通過它也能為一個方法產生相同的效果,這已經不是空想。
(如果你想知道為什么’m’是實例變量的名稱的***個字母,’m’往往是實例變量的公認約定。它代表了’member'(成員)的意思)。
不管你是否認為實例變量的前綴’m’是一個好注意,在這有一個知識,Android Studio能夠幫助你編寫任何你想要實現(xiàn)的公認約定。例如,在你為實例變量生成getters、setters和connstructor參數(shù)時,你可以使用Android Studio代碼風格對話框的設置使Android Studio在你的實例變量前自動添加’m’和移除’m’。
Android Studio能夠做的遠不止于此。學習Android Studio從學習快捷鍵和模版是不錯的開始。
4.一個函數(shù)只做一件事
在我寫的眾多類中的一個類存在一個方法我寫了有100多行。這類的方法是非常難以讀懂、修改和重用。努力讓一個方法只做一件事情。顯然,這意味著你應該對超過20行的方法持有懷疑態(tài)度。這里,你可以使用Android Studio來幫助你發(fā)現(xiàn)有問題的方法:
5.向聰明和有經驗的人學習
這可能聽起來微不足道,但是這是我開發(fā)我的***個應用時候犯下的錯誤。
當你開發(fā)一個應用的時候,你會犯別人已經犯過的錯誤。向別人學習,你可以避免犯別人犯過的錯誤來節(jié)約你的時間。我在我的***個應用中浪費了大量的時間犯錯,這些錯誤如果我花點時間向有經驗的軟件開發(fā)工程師學習就可以避免。
閱讀Pragmatic Programmer,然后閱讀Effective Java。這兩本書會幫助你避免開發(fā)新手常犯的錯誤。在你學習了這兩本書后,不停地尋找聰明的人并向他們學習。
6.使用類庫
當你開發(fā)應用的時候,你可能會遇到一些聰明人和有經驗人已經解決過的問題。而且,許多這些問題的解決方案是可以作為開源庫的,充分利用它們。
在我的***個應用中,我寫了一些類庫已經提供的功能代碼。其中一些是java標準庫,還有一些是第三方類庫,如Retrofit和Picasso。如果你不確定你使用什么樣的類庫,你可以做下面3件事情:
- 聽Google IO Fragmented廣播。在這期間,詢問這些開發(fā)者什么第三方類庫類庫對Android很重要。
- 訂閱Android周刊。這里包含了一部分***的類庫,時刻注意哪些對自己有用。
- 尋找那些能夠解決與你在開發(fā)應用中遇到問題類似的開源應用。你可能發(fā)現(xiàn)某個應用使用的第三方類庫就是你想要的,或者你會發(fā)現(xiàn)一個你所不知道的java類庫。
總結
開發(fā)優(yōu)秀的Android應用是非常困難的。不要犯曾經犯下的錯誤來難為自己。如果你發(fā)現(xiàn)我寫的代碼中的錯誤請在評論中告訴我。(誤導性評論比沒有評論更糟糕)。如果你認為這篇文章對于新手開發(fā)者有用,請分享它。解決他們的一些令人頭疼的難題。