前言
上一節我們通過一個Demo熟悉了Eclipse的基本使用、如何在模擬器和手機中運行以及如何打包成APK,但沒具體編寫代碼,相信很多同學已經按耐不住了吧,這一節我們會動手編寫代碼來熟悉Android SDK的情況和JAVA的一些特性。
聲明
本系列文章不是教程,僅為筆記,如有不當之處請指正。
歡迎轉載,轉載請保留原出處:http://www.cnblogs.com/rayee
正文
我們先了解一下編寫程序都要涉及到哪些東西,熟悉一下SDK的基本組件,然后編寫一個很簡單的小程序。
一、分析Demo
在上一節建立的工程Demo下,打開src/com.android.demo下的DemoActivity.java,如下所示:
Demo程序的代碼就只有13行,我們依次來分析一下:
package com.android.demo; /** 申明這個文件的代碼屬於包“com.android.demo” */ import android.app.Activity;/** 從Android SDK中引用Activity組件 */ import android.os.Bundle; /** 從Android SDK中引用Bundle組件 */ public class DemoActivity extends Activity { /** 新建類DemoActivity,繼承Activity,它就擁有Activity的特性了 */ /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { /** 重寫基類的同名函數,程序運行候創建Activity時被調用 */ super.onCreate(savedInstanceState); /** 調用基類的同名函數 */ setContentView(R.layout.main); /** 設置試圖,用於顯示界面 */ } }
第1行,聲明代碼屬於哪個包,這里的包名得與文件所在的包對應上,否則會報錯。
第3、4行,引用組件。這里的“引用”並不像其他語言的include那樣將文件包含進來,只是告訴編譯器,后面會使用到這里面的成員。
關於Package 與 Import的詳細說明,>>請到這里查看。
第6行,新建一個類DemoActivity,繼承Activity。JAVA是一門完全面向對象的語言,所有東西都要封裝在類里面,之前不熟悉面向對象的朋友估計會很不習慣(話說我之前用PHP做WEB開發,哪里都能寫實現…)。DemoActivity類繼承了Activity的特性,就屬於一個“Activity”了(前面提過,Activity是Android中的基本組件之前,非常之基礎,任何有界面的程序都有它)。
想深入了解“面向對象”的同學,>>請到這里查看。
第9行,重載onCreate函數。有編程經驗的同學看到on前綴就知道這個函數是個回調函數,屬於小受受,只能“被”,它在Activity這個界面開始創建時被調用。
第10行,調用基類的同名函數。基類還有些事情要處理呢,得通知他。
第11行,指定用哪個視圖來顯示界面。從字面上可以看到setContentView(R.layout.main),采用R.layout.main作為試圖,那么R.layout.main代表什么?我們要修改的話從哪里下手呢呢?
我們在上一節介紹工程文件的時候介紹過一個由IDE自動維護的文件夾gen,里面有個R.java文件,有同學可能明白了,這里就是引用里面的內容,如下所示:
R.layout.main就是R.layout類里面的一個屬性,值為0x7f030000,一個資源ID,那么它指向哪里呢?
上圖可以看到,真正的視圖布局文件在這里。上一節講過,res文件夾下的資源會自動在R.java里面生成記錄,現在看到確實是如此。至於那個資源ID是根據什么規則生成的,那就沒研究了,反正他自動維護,我們樂得清閑。
一會兒我們要修改程序界面就可以從這里入手。
Demo程序的代碼部分就這么多,是不是覺得其實並沒那么難?呵呵。
█ 學過JAVA的同學可能會有疑問了:怎么沒有入口函數呢?
我們編寫Android程序是在Android SDK下進行的,SDK在背后完成了很多工作,包括程序從哪里運行、怎么渲染視圖等等,我們只需要寫程序的邏輯部分、視圖部分,對於這個程序里的代碼來說,DemoActivity類就相當於一個入口了(姑且稱之為入口Activity吧),這和原生的JAVA編程是有一點不一樣哈。
█ 喜歡動腦經的同學會想:一個程序可能有多個界面,就有多個Activity,那么怎么知道該選擇哪個Activity為入口呢?
上一節還提到過一個全局配置文件AndroidMainifest.xml,我們打開看看:
我們可以看到,在這個文件里面配置了所有Activity的信息,DemoActivity里面有兩個intent-filter,<action android:name="android.intent.action.MAIN" />,<category android:name="android.intent.category.LAUNCHER" />,發現了LAUNCHER字樣,可以猜測這個就是入口標記,我們一會兒驗證一下。
二、新建一個Activity
我們新建一個Activity,脫離自動生成的DemoActivity試試
在src下的com.android.demo上點擊右鍵 –> New –> Class
Name處填寫類的名稱,在這里我們填寫launcherActivity,Superclass處我們填寫android.app.Activity,就是Activity的基類,其余的不用修改,點擊”Finish“,結果如下圖所示:
可以看到,launcherActivity新建好了,還自動生成了部分代碼,真方便。
糟了,DemoActivity類是大寫字母開頭的,我們的是小寫的l開頭,還是統一一下吧:
在launcherActivity.java中直接修改類的名稱,將l修改為L,發現IDE報錯了(因為JAVA是區分大小寫的,類名必須和文件名一樣),把鼠標移動到錯誤的地方,彈出修改建議,我們選擇”Rename compilation unit to…“,如下圖所示:
報錯消失了,文件名也變為大寫開頭了,真方便…
依瓢畫葫蘆,把Bundle組件引入進來,import android.os.Bundle;
然后重載onCreate方法。這個必須重載,我們得在里面設置視圖呀,操作如下:
LauncherActivity文件上點擊右鍵,Source –> Override/ Implement Methods...,勾選onCreate,點擊”OK“,代碼就自動生成好了:
三、新建布局
這個Activity還沒有視圖,我們新建一個:
在res/layout上點擊右鍵,New –> Other
選擇Android XML Layout File,點擊”Next“,在下一個頁面輸入布局名稱”launcher“,點擊”Finish“,布局文件就創建好了:
現在的SDK自帶了可視化布局,直接往上拖就行了,不過想要做出好看的界面,還需要深入了解Android界面布局,以后遇到再詳細講解。
可點擊標注處切換可視化界面或XML編輯界面,很多XML頁面打開都有這個切換按鈕,可以進行切換。
這里我們要做一個啟動界面,中間加個加載圖標,一行文字即可。詳細過程不多敘述(因為我都還沒完全學會如何布局,不敢誤人子弟),最終界面如下所示:
XML文件內容如下,可復制粘貼到文件里:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <FrameLayout android:id="@+id/frameLayout1" android:layout_width="match_parent" android:layout_height="match_parent" > <ProgressBar android:id="@+id/progressBar1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" /> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="120dip" android:text="Welcome ..." android:textAppearance="?android:attr/textAppearanceLarge" /> </FrameLayout> </LinearLayout>
在LauncherActivity類的onCreate方法中加上設置視圖的代碼:
setContentView(R.layout.launcher);
這樣JAVA代碼就編寫好了,但還沒完,我們還需要在AndroidMainifest.xml文件中添加這個Activity的配置信息,同時將DemoActivity配置中的intent-filter移動到LauncherActivity配置中,驗證一下是否真的是入口標志,最終的配置信息如下:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.demo" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".DemoActivity" android:label="@string/app_name" > </activity> <activity android:name=".LauncherActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
一個新的Activity就編寫完成了,按照上一節的方法運行看看是否正確:
可以看到,我們親自編寫的Activity運行起來了。正如我們所料,intent-filter段中的那個配置信息確實是起到了標記入口Activity的作用。
程序運行了半天還是一直加載,怎么回事呢?因為程序中沒后續動作了。接下來我們修改程序讓它跳轉到DemoActivity中。
四、Activity之間的跳轉
這需要在LauncherActivity類中修改代碼,思路是在onCreate被調用、設置好視圖后,等待一段時間,再跳轉到DemoActivity。開始編碼:
Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { // TODO Auto-generated method stub Intent goIntent = new Intent(); goIntent.setClass(LauncherActivity.this, DemoActivity.class); startActivity(goIntent); } }, 3*1000);
這里我們新建了個計時器timer,添加了個任務,在3秒鍾后執行。跳轉的代碼位於第6、7、8行:
建立一個Intent,設置好起始地點(LauncherActivity),目的地點(DemoActivity),開始跳轉(startActivity)。
這段代碼位於setContentView(R.layout.launcher);之后,最終代碼如下所示:
package com.android.demo; import java.util.Timer; import java.util.TimerTask; import android.app.Activity; import android.content.Intent; import android.os.Bundle; public class LauncherActivity extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.launcher); Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { // TODO Auto-generated method stub Intent goIntent = new Intent(); goIntent.setClass(LauncherActivity.this, DemoActivity.class); startActivity(goIntent); } }, 3*1000); } }
保存,再次運行,看歡迎頁面是否在3秒鍾后跳轉到了主頁面。
五、遺留的問題
在這一節,又接觸了一些新東西,之前沒說明,可能有些同學早就產生疑問了,這里集中講一下:
█ 第二個import語句引入的Bundle是什么,后面一直沒用過?
Bundle的字面意思為:捆、束,一組東西,在Android中用來傳遞數據,表現為Key-Value鍵值對,可以從一個Activity傳遞數據到另一個Activity。在這個例子中我們還沒用到它,但onCreate函數的參數必須要它,所以,必須import…
█ 最后又用到了個Intent,是什么?
Intent,意圖,和Bundle類似,也是包含一組東西,但不僅僅是數據,還包含操作類型、操作對象等信息。在上面的例子中startActivity函數只需要一個goIntent就能實現跳轉功能,就是因為goIntent包含了操作所需的東西,如果需要傳遞其它信息,還需要更復雜的設置。
結尾
這一節我們編寫了一個完整的小程序,雖然它實際上沒什么用…
仔細想想接觸到的東西還是挺多,面向對象、繼承、資源引用、全局配置、Activity的創建、布局文件的創建、Activity之間跳轉。
今天還是沒能寫出牛叉的程序,可能同學們覺得太慢了,但只要每天堅持學習幾個知識點,學習新的東西,不間斷的堅持下去,一定會成為大牛的!
下一節我們寫個牛叉的:基站定位,會學習到SDK中其它API的調用,HTTP通信,JSON解析等相關知識。
如果你喜歡看到這些文字,請點擊右下角的”推薦“支持我一下,謝謝!