CSDN移動將持續為您優選移動開發的精華內容,共同探討移動開發的技術熱點話題,涵蓋移動應用、開發工具、移動游戲及引擎、智能硬件、物聯網等方方面面。如果您想投稿、參與內容翻譯工作,或尋求近匠報道,請發送郵件至tangxy#csdn.net(請把#改成@)。
我的第一個應用非常糟糕。事實上,它糟糕得以致于我從應用市場上刪除它,同時我甚至都不會在我的簡歷上羅列出它。如果我在開發之前能夠知道一些Android開發的事情,也不會糟糕到這步田地。
本文中所羅列的事情是你在開發第一個Android應用的時候需要牢記在大腦中的。我接下來將展示的實際錯誤均來自于我的第一個應用程序代碼中。把這些錯誤經驗牢記心頭能夠幫助你開發一個讓你引以為豪的應用。
當然,正如Code Standards所說:如果你所做的工作和你作為學生開發的Android應用類似,你很有可能會討厭你的應用。
如果一年前你寫的代碼對于你來說感覺還不錯,你很大程度上沒有進行足夠的學習。
——Code Standards 2015.5.21
如果你是一位經驗豐富的JAVA開發者,第1、2、5條很有可能對你沒有吸引力。另一方面,即使你從來沒有犯過這些例子中的錯誤,第3、4條也可能向你展示一些很酷的事物,你可以利用一款也許你不知道的軟件——Android Studio去實現這些事物。
1. 不要持有Context的靜態引用
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將不會被垃圾回收(GC),除非靜態變量被從新分配到不同的Activity。這是因為mMeTrackerStore是靜態變量,而靜態變量的內存是不會被回收,直到應用程序退出才回收。如果你正在試圖做這樣的事情,你的代碼很有可能有嚴重的錯誤。尋找幫助吧,可能看看Google的Udacity課程“Android Development for Beginners”能夠幫助你。
注:從技術上說,你可以對一個Application Context進行靜態變量引用而不引起內存泄露,但我不建議你這樣做。
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中,(非靜態)內部類有個對外部類實例有個隱式引用。
在這個例子中,任何GetLatAndLongAndUpdateCameraAsyncTask都有一個外部類DefineGeofenceFragment的引用。對于匿名類是同樣的,它們也有一個對包含它們的類的實例的一個隱式引用。
GetLatAndLongAndUpdateCameraAsyncTask對生命周期我們無法控制的Fragment對象有一個隱式引用。Android SDK負責創建和銷毀Fragment,如果GetLatAndLongAndUpdateCameraAsyncTask 因為正在運行而不能被垃圾回收,那么DefineGeofenceFragment也將因為具有隱式引用而保留不能被垃圾回收。
這里有一個很棒的Google視頻,解釋它為什么會發生這種事情(友情提示:需自備梯子哈)。
3. 使用Android Studio進行工作
public ViewPager getmViewPager { return mViewPager; }
這段代碼是我使用“Generate Getter”在Android Studio中進行生成的。這些getter保持了’m’前綴的實例變量,同樣通過它也能為一個方法產生相同的效果,這已經不是空想。
(如果你想知道為什么’m’是實例變量的名稱的第一個字母,’m’往往是實例變量的公認約定。它代表了’member'(成員)的意思)。
不管你是否認為實例變量的前綴’m’是一個好注意,在這有一個知識,Android Studio能夠幫助你編寫任何你想要實現的公認約定。例如,在你為實例變量生成getters、setters和connstructor參數時,你可以使用Android Studio代碼風格對話框的設置使Android Studio在你的實例變量前自動添加’m’和移除’m’。

Android Studio能夠做的遠不止于此。學習Android Studio從學習快捷鍵和模版是不錯的開始。
4. 一個函數只做一件事
在我寫的眾多類中,有一個類的一個方法我便寫了有100多行。這類的方法是非常難以讀懂、修改和重用,努力讓一個方法只做一件事情。顯然,這意味著你應該對超過20行的方法持有懷疑態度。這里,你可以使用Android Studio來幫助你發現有問題的方法:

5. 向聰明和有經驗的人學習
這可能聽起來微不足道,但是這是我開發第一個應用時候犯下的錯誤。
當你開發一個應用的時候,你會犯別人已經犯過的錯誤。向別人學習,你可以避免犯別人犯過的錯誤來節約你的時間。我在我的第一個應用中浪費了大量的時間去犯錯,這些錯誤如果我花點時間向有經驗的軟件開發工程師學習就可以避免。
閱讀Pragmatic Programmer,然后閱讀Effective Java。這兩本書會幫助你避免開發新手常犯的錯誤。在你學習了這兩本書后,不停地尋找聰明的人并向他們學習。
6. 使用類庫
當你開發應用的時候,你可能會遇到一些聰明人和有經驗人已經解決過的問題。而且,許多這些問題的解決方案是可以作為開源庫的,充分利用它們。
在我的第一個應用中,我寫了一些類庫已經提供的功能代碼。其中一些是Java標準庫,還有一些是第三方類庫,如Retrofit和Picasso。如果你不確定你使用什么樣的類庫,你可以做下面3件事情:
- 聽Google IO Fragmented廣播。在這期間,詢問這些開發者什么第三方類庫類庫對Android很重要。
- 訂閱Android周刊。這里包含了一部分最新的類庫,時刻注意哪些對自己有用。
- 尋找那些能夠解決與你在開發應用中遇到問題類似的開源應用。你可能發現某個應用使用的第三方類庫就是你想要的,或者你會發現一個你所不知道的Java類庫。
總結
開發優秀的Android應用是非常困難的,不要用重蹈覆轍來難為自己。如果你發現我寫的代碼中的錯誤請在評論中告訴我。(誤導性評論比沒有評論更糟糕)。如果你認為這篇文章對于新手開發者有用,請分享它,以解決他們的一些令人頭疼的難題。