1. 程式人生 > >Android基礎知識整理

Android基礎知識整理

1. 虛擬機器

認知: ART是趨勢,DalVik已經慢慢在被淘汰

ART,即Android Runtime。ART 的機制與 Dalvik 不同。在Dalvik下,應用每次執行的時候,位元組碼都需要通過即時編譯器(just in time ,JIT)轉換為機器碼,這會拖慢應用的執行效率,而在ART 環境中,應用在第一次安裝的時候,位元組碼就會預先編譯成機器碼,使其成為真正的本地應用。這個過程叫做預編譯(AOT,Ahead-Of-Time)。這樣的話,應用的啟動(首次)和執行都會變得更加快速。

2. 相關資源

3. 元件

3.1 Button

3.1.1 Button點選事件觸發的兩種方法:
  1. 在activity中bt.setOnClickListener(new onClickListener())
  2. 在layout中,bt設定一個屬性android:onClick = "something",然後在activity中定義一個同名的方法public void something(View v){}這個方法所接收的引數為一個View物件,當按鈕被按下時,系統會呼叫這個something()方法

注意,在onClick方法中傳入的View物件是被點選的button物件,所以多個button可以共用一個點選監聽,只要在監聽裡面用bt.getId()來最終區分出來是哪個button就可以分別處理而不干擾。

有一個疑問就是:共用監聽or單獨監聽(每個button一個內部類)or在layout中設定onClick這幾種方式在消耗記憶體上有啥區別?

3.1.2 設定半透明度
  • 在xml檔案中:

    • 半透明:<Button android:background="#e0000000" ... />
    • 透明:<Button android:background="#00000000" ... />
  • 在java程式碼中:

    • btn.getBackground().setAlpha(100) //0~255透明度
  • 數值量:

    • 顏色和不透明度 (alpha) 值以十六進位制表示法表示。任何一種顏色的值範圍都是 0 到 255(00 到 ff)。
    • 對於 alpha,00 表示完全透明,ff 表示完全不透明。
    • 表示式順序是“aabbggrr”,其中“aa=alpha”(00 到 ff);“bb=blue”(00 到 ff);“gg=green”(00 到 ff);“rr=red”(00 到 ff)。
    • 例如,如果您希望對某疊加層應用不透明度為 50% 的藍色,則應指定以下值:7fff0000

4. 佈局

開發中用的最多的是linearlayoutrelativelayout

4.1 LinearLayout

單純線性佈局永遠不會發生元件的重疊

LinearLayout中的layout_weight屬性: layout_weight屬性用於分配LinearLayout中的的額外空間(extra space)。

如果View不想拉伸的話,layout_weight值設定為0。否則的話這些畫素會按比例分配到weight值大於0的所有View。

換句話說,也就是android:layout_weight屬性告知LinearLayout如何進行子元件的佈置安排。

4.2 RelativeLayout

relativelayout中預設的對齊方式是左對齊和頂部對齊,可以通過設定android:layout_align*="true"("id")或者layout_above="id"或者layout_toLeftOf="@id/*"等屬性來改變,而居中等可以通過android:centerIn*來設定

假設有兩個物件(id分別為tv1和tv2)第二個物件設定了兩個屬性alignRight="@id/tv1"alignLeft="@id/tv1",那麼第二個物件就會和第一個物件等寬

4.3 FrameLayout

幀佈局是五大布局中最簡單的佈局方式,在需要佈局中有空間重疊的情況下才使用。 frameLayout中的所有檢視都已以層疊的方式展現的。第一個新增到佈局中的檢視顯示在最底層,最後一個被放在最頂層。上一層的檢視會覆蓋下一層的檢視,因此該佈局類似於堆疊佈局。

  • framelayout中子檢視預設的對齊方式也是左對齊和頂部對齊,可以通過設定android:layout_gravity="left|buttom"等屬性來改變

  • framelayout中,空間的layout_margin屬性需要依賴layout_gravity屬性,否則設定無效。layout_margin所示的邊緣值是相對於控制元件的layout_gravity所定義的參考點而言的。

  • 如果以圖片作為linearLayout的背景,那麼將無法控制佈局的高和寬,其尺寸會不受控制地適應圖片的大小,因此採用frameLayout配合imageView新增可大小可控的背景

4.4 TableLayout

<TableLayout>
<!--tableRow中有幾個子標籤就有幾列-->
  <TableRow> </TableRow>
  <TavleRow> </TableRow>
</TableLayout>

寬高: 在表格佈局中每個tableRow的寬高是有個預設值的,預設的寬是match_parent預設的高是wrap_content,同時寬高也是不可更改的,改了也無效 可以在TableLayout中設定stretchColumns="*"設定拉伸列

分割線: 如果想在表格中插入一個分割線,可以在<TableLayout>中加入一個直接子標籤<TextView>,將其高度設為1個dp,設定下顏色就好了

兩個獨有的屬性: 可以通過layout_column=""直接設定某個元素在第幾列,這樣就可以不必從第0列開始 可以通過layout_span=""來設定某一個元素佔幾列

5. 讀寫檔案

儲存空間包括內部儲存空間和外部儲存空間

5.1 內部儲存空間(ROM)

內部儲存讀寫檔案不需要許可權,因為只能寫自己包內的檔案,其他包不能動,除非有root許可權

5.1.1 絕對路徑
File file = new File("data/data/com.example.*/file");
FileOutputStream fos = new FileOutStream(file);
fos.write(string.getBytes());
5.1.2 使用路徑api

可以通過getFilesDir()來獲得data/data/com.example.*/file資料夾的路徑.,所以可以這樣寫:

File file = new File(getFilesDir(),“name.txt”);

而通過getCacheDir()可以獲得 data/data/com.example.*/cache資料夾的路徑

從原始碼看,兩者的區別是:當rom空間不夠的時候,cache資料夾中的東西有可能會被系統刪除,但是不能指望系統去刪除,應該自己設定一個閾值 在設定中點選儲存,選擇相應的應用,可以選擇清除快取清除資料,前者會清空cache資料夾中的所有檔案,而後者會刪除包內所有的使用者檔案

5.2 外部儲存讀寫(sd卡)

外部儲存寫資料需要許可權WRITE_EXTERNAL_STORAGE,而讀資料則不一定,要看開發者選項裡面是否勾選了sd卡讀防寫

5.2.1 絕對路徑

各個廠商的sd卡的路徑差不多都不一樣,要注意

File file = new File("sdcard/file.*")
5.2.2 使用路徑api

這個api名字突出一個長啊,使用之前先判斷sd卡是否可用

if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
  File file = new File(Environment.getExternalStorageDirectory(),"name");
}

其中,sd卡的狀態可以有:

狀態 說明
REMOVE 沒有插sd卡
UNMOUNT sd卡已插,但是沒有掛載
CHECKING sd卡正在被系統遍歷
MOUNTED sd卡準備就緒,可以讀寫
MOUNTED_READ_ONLY sd卡可用,但是隻讀
5.2.3 獲取sd卡的剩餘空間

可以參看設定系統應用的原始碼,放在package/apps/Settings中,具體用的時候可以google找輪子

sd卡儲存空間 = 可用的區塊數量*區塊大小(blockSize)

5.3 檔案訪問許可權

許可權的表現形式: d rwx rwx rwx 一共十位

  • 在Android中,每一個應用都是一個獨立的使用者
  • d:代表資料夾,檔案是-
  • 第一個rwx:決定owner使用者對此檔案的許可權
    • r:讀
    • w:寫
    • x:執行(execute)

檔案訪問許可權

具體程式設計時,當我們需要在應用中寫入一個一定許可權的檔案的時候:

public void bt_click(View v){
  //此api會把檔案寫到data/data/com.xxx.xxx/files資料夾下
  try{
    FileOutputStream fos = openFileOutput("example.txt", MODE_WORLD_READABLE);
    fos.write("哈哈".getBytes());
    fos.close();
  }catch(Exception e){
    e.printStackTrace();
  }
}

其中要說明的是openFileOutput是Context提供的一個很要用的方法,但是隻能寫到本應用對應的資料夾下:

@openFileOutput方法

5.4 使用Shared Preference存取簡單資料

SharedPreferences的使用非常簡單,能夠輕鬆的存放資料和讀取資料。SharedPreferences只能儲存簡單型別的資料,例如,String、int等。一般會將複雜型別的資料轉換成Base64編碼,然後將轉換後的資料以字串的形式儲存在 XML檔案中,再用SharedPreferences儲存。

具體的方法參看博文: Android SharedPreferences使用以及原理詳解 **注意:**要使用Activity類的getSharedPreferences方法獲得SharedPreferences物件,而不要new一個新的物件,否則效率不高

6. 除錯時的小技巧

  1. 真機除錯時eclipse的file explorer打不開data資料夾: 當用真機開發Android時,連線了Eclipse後,預設在File Explorer下是達不開我們手機的data資料夾的,這裡打不開是因為許可權不足。以下有個小技巧可以解決這問題。 首先,測試機先root,然後在手機上安裝上Root Explorer 管理器(或類似軟體),再將/data/data及其子資料夾下的訪問許可權都修改為可讀可寫可執行即可。這時候再使用eclipse的File Explorer就可以展開了,這時候就可以檢視應用下的SQLite資料庫了。

  2. 當devices中的裝置顯示不出來的時候: 直接使用需要在cmd中cd到sdk的目錄下使用adb start-server指令,也可以將該目錄直接加入到系統變數的path中,這樣直接就在cmd任意位置輸入指令即可。本質是個socket。 相關的指令:

  • adb start-server其實任何一條adb指令都可以重啟adb
  • adb kill-server殺死程序
  • adb install apk的路徑安裝apk
  • adb uninstall com.tristan.something這裡是寫的包名
  • adb devices顯示所有連線的android裝置
  • adb shell進入android系統的命令列(linux)
  1. 當你的手機助手佔用的系統的adb的埠(5037)怎麼辦? 首先通過adb devices檢視埠,然後在windows下cmd使用netstat -ano檢視當前系統各個埠被什麼程序所佔用

  2. 專案組織檔案: manifeast中的package是android分辨應用的唯一標識,和gen目錄下的包名相同,與src目錄下的不同 當應用涉及到使用者許可權時,需要到manifesat中去新增許可權(可以通過視覺化操作)

  3. 檢視日誌: 在logcat中設定過濾器的時候最好根據Tag來過濾(比如System.out輸出的日誌的tag就是System.out,級別為Info),而不要用Application來過濾 logcat語句:

    Log.e(tag,string) Log.i(tag,string) …

  4. URI和URL的區別

//舉例,撥號邏輯
public void onclick(View v){
    EditText et = (EditText) findViewById(R.id.et);
    String phone = et.getText().toString();
    Intent intent = new Intent();
  intent.setAction(Intent.ACTION_CALL);
  intent.setData(Uri.parse("tel:" + phone));
}