[toc]
Android筆記
前言: 本筆記基于MacOS系統(tǒng)
學(xué)習(xí)意圖: 為了做逆向打基礎(chǔ)
筆記內(nèi)容: android的重要組件和功能(不死扣細(xì)節(jié))
學(xué)習(xí)目標(biāo): 拿到一套android代碼可以通過讀代碼方式可以理清自己需要的部分功能的實(shí)現(xiàn)邏輯.
附加目標(biāo): 當(dāng)需要寫android時,可以根據(jù)自己的需要快速定位開發(fā)
軟件(flutter、dart和vscode可以不裝)
jdk + flutter + android studio + dart+ vscode(機(jī)子性能好可以選android studio + android SDK + jdk)
安裝
1、jdk 12
mac自帶,建議自己配置一個java8,新版本總會有各種不兼容
2蔓倍、flutter sdk(如果不想寫原生android的話)
2.1 下載
地址:https://flutter.dev/docs/get-started/install
解壓到指定目錄: 如 ~
2.2 環(huán)境配置
官方教程: https://flutter.dev/docs/get-started/install/macos
在~/.zshrc(或者.bashrc、.bash_profile) 中最后一行添加
export PATH="$PATH:~/flutter/bin"
重新source ~/.zshrc
3位迂、vscode(機(jī)子性能不足,用vscode寫)
https://vscode.cdn.azure.cn/stable/26076a4de974ead31f97692a0d32f90d735645c0/VSCode-darwin-stable.zip
下載完畢后,安裝flutter和dart
dart安裝、配置
brew install dart
vim ~/.zshrc
# 最后兩行添加,其中DART_HOME為dart的安裝路徑
export DART_HOME=/usr/local/Cellar/dart/2.8.0-dev.0.0/bin
export PATH="${DART_HOME}:${PATH}"
4、AS(android studio)
4.1 下載
android studio下載
http://down-ww3.newasp.net/pcdown/big/android_studio_ide_mac.dmg
下載完畢后,直接安裝,遇到設(shè)置代理會報紅,取消即可.后面就是next -> next...
創(chuàng)建項(xiàng)目,項(xiàng)目命名規(guī)則為駝峰式,next...創(chuàng)建完一般情況下會報錯,暫時不管,到AS配置步驟解決
Android sdk下載
https://dl.google.com/android/repository/tools_r25.2.3-macosx.zip
# 解壓后,進(jìn)入tools目錄
cd tools
.android sdk
勾選Extras,然后下載.
gradle配置
cd ~
vim .zshrc(或者.bashrc)
# 在最后添加
# 配置gradle環(huán)境,GRADLE_HOME路徑為AS路徑下gradle下的gradle
export GRADLE_HOME=/Applications/Android\ Studio.app/Contents/gradle/gradle-4.4
export PATH=${PATH}:${GRADLE_HOME}/bin
# 退出保存 :wq
# 然后測試
gradle -version
------------------------------------------------------------
Gradle 4.4
------------------------------------------------------------
Build time: 2017-12-06 09:05:06 UTC
Revision: cf7821a6f79f8e2a598df21780e3ff7ce8db2b82
Groovy: 2.4.12
Ant: Apache Ant(TM) version 1.9.9 compiled on February 2 2017
JVM: 1.8.0_231 (Oracle Corporation 25.231-b11)
OS: Mac OS X 10.14.4 x86_64
AS配置
1、打開文件目錄下Gradle Scripts -> build.gradle
全選修改(設(shè)置國內(nèi)鏡像源)
buildscript {
repositories {
maven { url 'https://maven.aliyun.com/repository/google' }
maven{ url 'https://maven.aliyun.com/repository/jcenter'}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.0'
}
}
allprojects {
repositories {
maven { url 'https://maven.aliyun.com/repository/google' }
maven{ url 'https://maven.aliyun.com/repository/jcenter'}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
2诀黍、打開文件目錄下Gradle Scripts -> gradle-wrapper.propertiies
#Thu Jan 02 10:38:22 CST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
3袋坑、File -> Project structure
勾選 Idk location下的Use embezzlementdded JDK
4仗处、Preferences -> Build,Execution,Deployment -> Gradle -> Android Studi
勾選Enable embedded Maven repository
5眯勾、Try again
6、創(chuàng)建虛擬設(shè)備(可以直接連接手機(jī))
7婆誓、運(yùn)行第一個程序
筆記指南
一個完整的安卓系統(tǒng)大致上由一個界面使用各種布局方式承載各種組件,并且在組件上綁定各種事件,通過與用戶與組件的交互,激活與事件綁定的后臺邏輯,然后反饋給用戶,實(shí)現(xiàn)一個app的各種功能.
四大應(yīng)用組件
- Activity
- 服務(wù)
- 廣播接收器
- 內(nèi)容提供程序
Activity(界面)吃环、服務(wù)(調(diào)度器,大管家)、廣播接收器(全局消息)洋幻、內(nèi)容提供器(數(shù)據(jù)庫) (總結(jié))
Activity
Activity 是與用戶交互的入口點(diǎn)郁轻。它表示擁有界面的單個屏幕。例如文留,電子郵件應(yīng)用可能有一個顯示新電子郵件列表的 Activity好唯、一個用于撰寫電子郵件的 Activity 以及一個用于閱讀電子郵件的 Activity。盡管這些 Activity 通過協(xié)作在電子郵件應(yīng)用中形成一種緊密結(jié)合的用戶體驗(yàn)燥翅,但每個 Activity 都獨(dú)立于其他 Activity 而存在骑篙。因此,其他應(yīng)用可以啟動其中任何一個 Activity(如果電子郵件應(yīng)用允許)森书。例如靶端,相機(jī)應(yīng)用可以啟動電子郵件應(yīng)用內(nèi)用于撰寫新電子郵件的 Activity,以便用戶共享圖片凛膏。Activity 有助于完成系統(tǒng)和應(yīng)用程序之間的以下重要交互:
追蹤用戶當(dāng)前關(guān)心的內(nèi)容(屏幕上顯示的內(nèi)容)杨名,以確保系統(tǒng)繼續(xù)運(yùn)行托管Activity 的進(jìn)程。
了解先前使用的進(jìn)程包含用戶可能返回的內(nèi)容(已停止的 Activity)猖毫,從而更優(yōu)先保留這些進(jìn)程台谍。
幫助應(yīng)用處理終止其進(jìn)程的情況,以便用戶可以返回已恢復(fù)其先前狀態(tài)的 Activity吁断。
提供一種途徑典唇,讓應(yīng)用實(shí)現(xiàn)彼此之間的用戶流,并讓系統(tǒng)協(xié)調(diào)這些用戶流胯府。(此處最經(jīng)典的示例是共享介衔。)
服務(wù)
服務(wù)是一個通用入口點(diǎn),用于因各種原因使應(yīng)用在后臺保持運(yùn)行狀態(tài)骂因。它是一種在后臺運(yùn)行的組件炎咖,用于執(zhí)行長時間運(yùn)行的操作或?yàn)檫h(yuǎn)程進(jìn)程執(zhí)行作業(yè)。服務(wù)不提供界面寒波。例如乘盼,當(dāng)用戶使用其他應(yīng)用時,服務(wù)可能會在后臺播放音樂或通過網(wǎng)絡(luò)獲取數(shù)據(jù)俄烁,但這不會阻斷用戶與 Activity 的交互绸栅。諸如 Activity 等其他組件可以啟動服務(wù),使該服務(wù)運(yùn)行或綁定到該服務(wù)页屠,以便與其進(jìn)行交互粹胯。事實(shí)上蓖柔,有兩種截然不同的語義服務(wù)可以告知系統(tǒng)如何管理應(yīng)用:已啟動服務(wù)會告知系統(tǒng)使其運(yùn)行至工作完畢。此類工作可以是在后臺同步一些數(shù)據(jù)风纠,或者在用戶離開應(yīng)用后繼續(xù)播放音樂况鸣。在后臺同步數(shù)據(jù)或播放音樂也代表了兩種不同類型的已啟動服務(wù),而這些服務(wù)可以修改系統(tǒng)處理它們的方式:
音樂播放是用戶可直接感知的服務(wù)竹观,因此镐捧,應(yīng)用會向用戶發(fā)送通知,表明其希望成為前臺臭增,從而告訴系統(tǒng)此消息懂酱;在此情況下,系統(tǒng)明白它應(yīng)盡全力維持該服務(wù)進(jìn)程運(yùn)行誊抛,因?yàn)檫M(jìn)程消失會令用戶感到不快玩焰。
通常,用戶不會意識到常規(guī)后臺服務(wù)正處于運(yùn)行狀態(tài)芍锚,因此系統(tǒng)可以更自由地管理其進(jìn)程昔园。如果系統(tǒng)需要使用 RAM 來處理用戶更迫切關(guān)注的內(nèi)容,則其可能允許終止服務(wù)(然后在稍后的某個時刻重啟服務(wù))并炮。
綁定服務(wù)之所以能運(yùn)行默刚,原因是某些其他應(yīng)用(或系統(tǒng))已表示希望使用該服務(wù)。從根本上講逃魄,這是為另一個進(jìn)程提供 API 的服務(wù)荤西。因此,系統(tǒng)會知曉這些進(jìn)程之間存在依賴關(guān)系伍俘,所以如果進(jìn)程 A 綁定到進(jìn)程 B 中的服務(wù)邪锌,系統(tǒng)便知道自己需使進(jìn)程 B(及其服務(wù))為進(jìn)程 A 保持運(yùn)行狀態(tài)。此外癌瘾,如果進(jìn)程 A 是用戶關(guān)心的內(nèi)容觅丰,系統(tǒng)隨即也知道將進(jìn)程 B 視為用戶關(guān)心的內(nèi)容。由于存在靈活性(無論好壞)妨退,服務(wù)已成為非常有用的構(gòu)建塊妇萄,并且可實(shí)現(xiàn)各種高級系統(tǒng)概念。動態(tài)壁紙咬荷、通知偵聽器冠句、屏幕保護(hù)程序、輸入方法幸乒、無障礙功能服務(wù)以及眾多其他核心系統(tǒng)功能均可構(gòu)建為在其運(yùn)行時由應(yīng)用實(shí)現(xiàn)懦底、系統(tǒng)綁定的服務(wù)。
廣播接收器
借助廣播接收器組件罕扎,系統(tǒng)能夠在常規(guī)用戶流之外向應(yīng)用傳遞事件聚唐,從而允許應(yīng)用響應(yīng)系統(tǒng)范圍內(nèi)的廣播通知丐重。由于廣播接收器是另一個明確定義的應(yīng)用入口,因此系統(tǒng)甚至可以向當(dāng)前未運(yùn)行的應(yīng)用傳遞廣播拱层。例如,應(yīng)用可通過調(diào)度提醒來發(fā)布通知宴咧,以告知用戶即將發(fā)生的事件根灯。而且,通過將該提醒傳遞給應(yīng)用的廣播接收器掺栅,應(yīng)用在提醒響起之前即無需繼續(xù)運(yùn)行烙肺。許多廣播均由系統(tǒng)發(fā)起,例如氧卧,通知屏幕已關(guān)閉桃笙、電池電量不足或已拍攝照片的廣播。應(yīng)用也可發(fā)起廣播沙绝,例如搏明,通知其他應(yīng)用某些數(shù)據(jù)已下載至設(shè)備,并且可供其使用闪檬。盡管廣播接收器不會顯示界面星著,但其可以創(chuàng)建狀態(tài)欄通知,在發(fā)生廣播事件時提醒用戶粗悯。但廣播接收器更常見的用途只是作為通向其他組件的通道虚循,旨在執(zhí)行極少量的工作。例如样傍,它可能會根據(jù)帶 JobScheduler 的事件調(diào)度 JobService 來執(zhí)行某項(xiàng)工作
廣播接收器作為 BroadcastReceiver 的子類實(shí)現(xiàn)横缔,并且每條廣播都作為 Intent 對象進(jìn)行傳遞。如需了解詳細(xì)信息衫哥,請參閱 BroadcastReceiver 類茎刚。
內(nèi)容提供程序
內(nèi)容提供程序管理一組共享的應(yīng)用數(shù)據(jù)须眷,您可以將這些數(shù)據(jù)存儲在文件系統(tǒng)间影、SQLite 數(shù)據(jù)庫、網(wǎng)絡(luò)中或者您的應(yīng)用可訪問的任何其他持久化存儲位置戈稿。其他應(yīng)用可通過內(nèi)容提供程序查詢或修改數(shù)據(jù)(如果內(nèi)容提供程序允許)笛质。例如泉沾,Android 系統(tǒng)可提供管理用戶聯(lián)系人信息的內(nèi)容提供程序。因此妇押,任何擁有適當(dāng)權(quán)限的應(yīng)用均可查詢內(nèi)容提供程序(如 ContactsContract.Data)跷究,以讀取和寫入特定人員的相關(guān)信息。我們很容易將內(nèi)容提供程序看作數(shù)據(jù)庫上的抽象敲霍,因?yàn)槠鋬?nèi)置的大量 API 和支持時常適用于這一情況俊马。但從系統(tǒng)設(shè)計(jì)的角度看丁存,二者的核心目的不同。對系統(tǒng)而言柴我,內(nèi)容提供程序是應(yīng)用的入口點(diǎn)解寝,用于發(fā)布由 URI 架構(gòu)識別的已命名數(shù)據(jù)項(xiàng)。因此艘儒,應(yīng)用可以決定如何將其包含的數(shù)據(jù)映射到 URI 命名空間聋伦,進(jìn)而將這些 URI 分發(fā)給其他實(shí)體。反之界睁,這些實(shí)體也可使用分發(fā)的 URI 來訪問數(shù)據(jù)觉增。在管理應(yīng)用的過程中,系統(tǒng)可以執(zhí)行以下特殊操作:
分配 URI 無需應(yīng)用保持運(yùn)行狀態(tài)翻斟,因此 URI 可在其所屬的應(yīng)用退出后繼續(xù)保留逾礁。當(dāng)系統(tǒng)必須從相應(yīng)的 URI 檢索應(yīng)用數(shù)據(jù)時,系統(tǒng)只需確保所屬應(yīng)用仍處于運(yùn)行狀態(tài)访惜。
這些 URI 還會提供重要的細(xì)粒度安全模型嘹履。例如,應(yīng)用可將其所擁有圖像的 URI 放到剪貼板上债热,但將其內(nèi)容提供程序鎖定植捎,以便其他應(yīng)用程序無法隨意訪問它。當(dāng)?shù)诙€應(yīng)用嘗試訪問剪貼板上的 URI 時阳柔,系統(tǒng)可允許該應(yīng)用通過臨時的 URI 授權(quán)來訪問數(shù)據(jù)焰枢,這樣便只能訪問 URI 后面的數(shù)據(jù),而非第二個應(yīng)用中的其他任何內(nèi)容舌剂。
內(nèi)容提供程序也適用于讀取和寫入您的應(yīng)用不共享的私有數(shù)據(jù)。
聲明組件
- Activity --- <activity>元素
- 服務(wù) --- <service>元素
- 廣播接收器 --- <receiver>元素
- 內(nèi)容提供程序 --- <provider>元素
布局
- LinearLayout
- RelativeLayout
- TableLayout
- FrameLayout
- AbsoluteLayout(待刪除,不建議使用)
- GridLyout
布局就是按照設(shè)計(jì)圖選擇最合適的排版模板(總結(jié))
LinearLayout
線性布局是Android中較為常用的布局方式霍转,使用LinearLayout標(biāo)簽荐绝。線性布局主要有兩種形式,一種是水平線性布局避消,一種是垂直線性布局低滩。需要注意的是Android的線性布局不會換行,當(dāng)組件一個挨著一個地排列到頭之后岩喷,剩下的組件將不會被顯示出來恕沫。
RelativeLayout
相對布局,使用RelativeLayout標(biāo)簽纱意。相對布局通常有兩種形式婶溯,一種是相對于容器而言的,一種是相對于控件而言的。
TableLayout
表格布局就是讓控件以表格的形式來排列控件迄委,只要將控件放在單元格中褐筛,控件就可以整齊地排列,使用TableLayout標(biāo)簽叙身。
TableLayout繼承了 LinearLayout渔扎,因此它的本質(zhì)依然是線性布局管理器。每次向TableLayout中添加一個TableRow信轿,該TableRow就是一個表格行晃痴,TableRow也是容器,因此它也可以不斷地添加其他組件虏两,每添加一個子組件該表格就增加一列愧旦。如果直接向TableLayout中添加組件世剖,那么這個組件將直接占用一行定罢。
在表格布局中,列的寬度由該列中最寬的那個單元格決定旁瘫,整個表格布局的寬度則取決于父容器的寬度(默認(rèn)總是占滿父容器本身)祖凫。
FrameLayout
幀布局為每個加入其中的控件創(chuàng)建一個空白區(qū)域(稱為一幀,每個控件占據(jù)一 幀)酬凳。釆用幀布局方式設(shè)計(jì)界面時惠况,只能在屏幕左上角顯示一個控件,如果添加多個控件宁仔,這些控件會按照順序在屏幕的左上角重疊顯示稠屠。
AbsoluteLayout(待刪除,不建議使用)
絕對布局需要通過指定x、y坐標(biāo)來控制每一個控件的位置翎苫,放入該布局的控件需要通過android:layout_x和android:layout_y 兩個屬性指定其準(zhǔn)確的坐標(biāo)值权埠,并顯示在屏幕上。
需要注意的是當(dāng)使用AbsoluteLayout作為布局容器時煎谍,布局容器不再管理子組件的位置和大小攘蔽,都需要開發(fā)人員自己控制。使用絕對布局時呐粘,每個子組件都可指定如下兩個XML屬性满俗。
GridLyout
網(wǎng)格布局實(shí)現(xiàn)了控件的交錯顯示,能夠避免因布局嵌套對設(shè)備性能的影響作岖,更利于自由布局的開發(fā)唆垃。網(wǎng)格布局用一組無限細(xì)的直線將繪圖區(qū)域分成行、列和單元痘儡,并指定控件的顯示區(qū)域和控件在該區(qū)域的顯示方式
View
部分組件
- TextView
- EditText
- Button
- CheckBox
- RadioBox
- Boggle
- Switch
- ImageView
- ImageButton
- ZoomButton
View實(shí)際上就是界面展示的各種組件,組件配合布局構(gòu)成了用戶展示界面(總結(jié))
Android 應(yīng)用的界面 (UI) 以布局和微件的層次結(jié)構(gòu)形式構(gòu)建而成降盹。布局是 ViewGroup
對象,即控制其子視圖在屏幕上的放置方式的容器。微件是 View
對象蓄坏,即按鈕和文本框等界面組件价捧。
graph TD
A[ViewGroup] --> B[ViewGroup]
A[ViewGroup] --> C[View]
A[ViewGroup] --> D[View]
B[ViewGroup] --> E[View]
B[ViewGroup] --> F[View]
TextView
功能: 在界面上顯示文本
父類: View
子類: EditText、Button
EditText
- 功能: 接收用戶輸入
- 父類: TextView
Button
- 功能: 綁定點(diǎn)擊事件,實(shí)現(xiàn)某些邏輯
- 父類: TextView
CheckBox
- 功能: 多選
RadioBox
- 功能: 單選
Boggle
- 功能: 選中
Switch
- 功能: 切換
ImageView
- 功能: 展示圖片
ImageButton
- 功能: 帶有圖片的按鈕
ZoomButton
- 放大縮曉
事件 (重要)
Android事件處理方式分兩種方式:
- 基于監(jiān)聽的事件處理
- 基于回調(diào)的事件處理
**觸發(fā)事件后,事件傳播流程,用戶界面的各個View(組件)配合事件構(gòu)成app的各種功能(總結(jié)): **
graph LR
A(事件源) -.觸發(fā)事件.-> B(事件監(jiān)聽器)
subgraph 注意事項(xiàng)
B(事件監(jiān)聽器) -.返回true.-> C(事件監(jiān)聽處理)
C(事件監(jiān)聽處理) -.返回true.-> D(事件回調(diào)處理)
C(事件監(jiān)聽處理) -.返回false.-> E(結(jié)束)
B(事件監(jiān)聽器) -.返回false.-> F(結(jié)束)
end
1涡戳、基于監(jiān)聽的事件處理
Event Source (事件源):事件發(fā)生的場所结蟋,通常就是各個組件,例如按鈕渔彰、窗口嵌屎、菜單等。
Event (事件):事件封裝了界面組件上發(fā)生的特定事情(通常就是一次用戶操作)恍涂。如果程序需要獲得界面組件上所發(fā)生事件的相關(guān)信息宝惰,一般通過Event對象來取得。
Event Listener (事件監(jiān)聽器):負(fù)責(zé)監(jiān)聽事件源所發(fā)生的事件再沧,并對各種事件做出相應(yīng)的響應(yīng)尼夺。
當(dāng)用戶按下一個按鈕或者單擊某個菜單項(xiàng)時,這些動作就會激發(fā)一個相應(yīng)的事件炒瘸,該事件就會觸發(fā)事件源上注冊的事件監(jiān)聽器(特殊的Java對象)淤堵,事件監(jiān)聽器調(diào)用對應(yīng)的事件處理器 (事件監(jiān)聽器里的實(shí)例方法)來做出相應(yīng)的響應(yīng)。
每個組件均可以針對特定的事件指定一個事件監(jiān)聽器顷扩,每個事件監(jiān)聽器也可監(jiān)聽一個或多個事件源拐邪。因?yàn)橥粋€事件源上可能發(fā)生多種事件,委派式事件處理方式可以把事件源上所有可能發(fā)生的事件分別授權(quán)給不同的事件監(jiān)聽器來處理隘截;同時也可以讓一類事件都使用同一個事件監(jiān)聽器來處理扎阶。
在基于監(jiān)聽的事件處理模型中,事件監(jiān)聽器必須實(shí)現(xiàn)事件監(jiān)聽器接口婶芭,Android為不同的界面組件提供了不同的監(jiān)聽器接口东臀,這些接口通常以內(nèi)部類的形式存在。以View類為例雕擂,它包含了如下幾個內(nèi)部接口啡邑。
View.OnClickListener:單擊事件的事件監(jiān)聽器必須實(shí)現(xiàn)的接口。
View.OnCreateContextMenu Listener :創(chuàng)建上下文菜單事件的事件監(jiān)聽器必須實(shí)現(xiàn)的接口井赌。
View.onFocusChangeListener:焦點(diǎn)改變事件的事件監(jiān)聽器必須實(shí)現(xiàn)的接口谤逼。
View.OnKeyListener:按鍵事件的事件監(jiān)聽器必須實(shí)現(xiàn)的接口。
View.OnLongClickListener:長按事件的事件監(jiān)聽器必須實(shí)現(xiàn)的接口仇穗。
View.OnTouchListener:觸摸事件的事件監(jiān)聽器必須實(shí)現(xiàn)的接口流部。
實(shí)現(xiàn)形式:
- 使用匿名內(nèi)部類作為事件監(jiān)聽器
- 使用內(nèi)部類作為事件監(jiān)聽器
- 使用外部類作為事件監(jiān)聽器
- 直接使用Activity作為事件監(jiān)聽器
- 直接綁定到標(biāo)簽
實(shí)例:
layout.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">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="用戶名: "
android:textSize="16sp" />
<EditText
android:id="@+id/name_et"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請輸入用戶名"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="密碼: "
android:textSize="16sp"/>
<EditText
android:id="@+id/pwd_et"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請輸入密碼"/>
<Button
android:id="@+id/login_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="普通按鈕"/>
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
EditText mNameEt = null;
EditText mPasswordEt = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout);
// 獲取界面組件
mNameEt = findViewById(R.id.name_et);
mPasswordEt = findViewById(R.id.pwd_et);
Button btnClick = findViewById(R.id.login_btn);
btnClick.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view){
String name = mNameEt.getText().toString();
String password = mPasswordEt.getText().toString();
Toast.makeText(MainActivity.this, "按鈕被點(diǎn)擊" + name + password,
Toast.LENGTH_SHORT).show();
}
});
}
2、基于回調(diào)的事件處理
對于基于回調(diào)的事件處理模型來說纹坐,事件源與事件監(jiān)聽器是統(tǒng)一的枝冀,或者說事件監(jiān)聽器完全消失了。當(dāng)用戶在GUI組件上激發(fā)某個事件時,組件自己特定的方法將會負(fù)責(zé)處理該事件果漾。
為了實(shí)現(xiàn)回調(diào)機(jī)制的事件處理球切,Android為所有GUI組件都提供了一些事件處理的回調(diào)方法,以View為例绒障,該類包含如下方法吨凑。
boolean onKeyDown(int keyCode, KeyEvent event):當(dāng)用戶在該組件上按下某個按鍵時觸發(fā)該方法。
boolean onKeyLongPress(int keyCode, KeyEvent event):當(dāng)用戶在該組件上長按某個按鍵時觸發(fā)該方法户辱。
boolean onKeyShortcut(int keyCode, KeyEvent event):當(dāng)一個鍵盤快捷鍵事件發(fā)生時觸發(fā)該方法鸵钝。
boolean onKeyUp(int keyCode, KeyEvent event):當(dāng)用戶在該組件上松開某個按鍵時觸發(fā)該方法。
boolean onTouchEvent(MotionEvent event):當(dāng)用戶在該組件上觸發(fā)觸摸屏事件時觸發(fā)該方法庐镐。
boolean onTrackballEvent(MotionEvent event):當(dāng)用戶在該組件上觸發(fā)軌跡球事件時觸發(fā)該方法恩商。
void onFocusChanged(boolean gainFocus, int direction, Rect previously FocusedRect):當(dāng)組件的焦點(diǎn)發(fā)生改變時觸發(fā)該方法。和前面的6個方法不同必逆,該方法只能夠在View中重寫怠堪。
Android系統(tǒng)事件響應(yīng)
對Android系統(tǒng)事件的響應(yīng)處理,實(shí)際上時對Configuration類的處理,系統(tǒng)事件響應(yīng)主要解決app共享系統(tǒng)資源問題(總結(jié))
在開發(fā)Android應(yīng)用時,有時候可能需要讓應(yīng)用程序隨系統(tǒng)設(shè)置而進(jìn)行調(diào)整末患,比如判斷系統(tǒng)的屏幕方向研叫、判斷系統(tǒng)方向的方向?qū)Ш皆O(shè)備等锤窑。除此之外璧针,有時候可能還需要讓應(yīng)用程序監(jiān)聽系統(tǒng)設(shè)置的更改,對系統(tǒng)設(shè)置的更改做出響應(yīng).
Configuration類專門用于描述手機(jī)設(shè)備上的配置信息渊啰,這些配置信息既包括用戶特定的配置項(xiàng)探橱,也包括系統(tǒng)的動態(tài)設(shè)備配置。程序可調(diào)用Activity的如下方法來獲取系統(tǒng)的Configuration對象:
Configurationcfg=getResources().getConfiguration();
一旦獲得了系統(tǒng)的Configuration對象绘证,就可以使用該對象提供的如下常用屬性來獲取系統(tǒng)的配置信息隧膏。
常用的配置常量
densityDpi:屏幕密度。
fontScale:當(dāng)前用戶設(shè)置的字體的縮放因子嚷那。
hardKeyboardHidden:判斷硬鍵盤是否可見胞枕,有兩個可選值:
HARDKEYBOARDHIDDEN_NO,值為十六進(jìn)制的0魏宽。
HARDKEYBOARDHIDDEN_YES腐泻,值為十六進(jìn)制的1。
keyboard:獲取當(dāng)前關(guān)聯(lián)額鍵盤類型:該屬性的返回值:
KEYBOARD_12KEY:只有12個鍵的小鍵盤队询。
KEYBOARD_NOKEYS:無鍵盤派桩。
KEYBOARD_QWERTY:普通鍵盤。
keyboardHidden:該屬性返回一個boolean值用于標(biāo)識當(dāng)前鍵盤是否可用蚌斩。該屬性不僅會判斷系統(tǒng)的硬件鍵盤铆惑,也會判斷系統(tǒng)的軟鍵盤(位于屏幕)。
locale:獲取用戶當(dāng)前的語言環(huán)境。
mcc:獲取移動信號的國家碼员魏。
mnc:獲取移動信號的網(wǎng)絡(luò)碼丑蛤。
ps:國家代碼和網(wǎng)絡(luò)代碼共同確定當(dāng)前手機(jī)網(wǎng)絡(luò)運(yùn)營商。
navigation:判斷系統(tǒng)上方向?qū)Ш皆O(shè)備的類型撕阎。該屬性的返回值:
NAVIGATION_NONAV:無導(dǎo)航盏阶。
NAVIGATION_DPAD:DPAD導(dǎo)航。
NAVIGATION_TRACKBALL:軌跡球?qū)Ш健?
NAVIGATION_WHEEL:滾輪導(dǎo)航闻书。
orientation:獲取系統(tǒng)屏幕的方向名斟。該屬性的返回值:
ORIENTATION_LANDSCAPE:橫向屏幕。
ORIENTATION_PORTRAIT:豎向屏幕魄眉。
screenHeightDp砰盐,screenWidthDp:屏幕可用高和寬,用dp表示坑律。
touchscreen:獲取系統(tǒng)觸摸屏的觸摸方式岩梳。該屬性的返回值:
TOUCHSCREEN_NOTOUCH:無觸摸屏。
TOUCHSCREEN_STYLUS:觸摸筆式觸摸屏晃择。
TOUCHSCREEN_FINGER:接收手指的觸摸屏冀值。
如果程序需要監(jiān)聽系統(tǒng)設(shè)置的更改,則可以考慮重寫Activity的onConfigurationChanged (Configuration newConfig)方法宫屠,該方法是一個基于回調(diào)的事件處理方法:當(dāng)系統(tǒng)設(shè)置發(fā)生更改時列疗,該方法會被自動觸發(fā)。
當(dāng)然浪蹂,為了讓Activity能監(jiān)聽系統(tǒng)配置更改的事件抵栈,需要在配置Activity時指定 androidiconfigChanges 屬性,該屬性可以支持 mcc坤次、mnc古劲、locale、touchscreen缰猴、keyboard产艾、keyboardHidden、navigation滑绒、orientation闷堡、screenLayout、uiMode蹬挤、screenSize缚窿、smallestScreenSize、fontScale等屬性值焰扳。
Activity
Activity是Android組件中最基本也是最常用的一種組件倦零,在一個Android應(yīng)用中误续,一個Activity通常就是一個單獨(dú)的屏幕。每一個Activity都被實(shí)現(xiàn)為一個獨(dú)立的類扫茅,并且繼承于Activity這個基類蹋嵌。
Activity生命周期
實(shí)例:
Task
Android中對于Activity的管理采用Task的概念,在應(yīng)用程序中每個被創(chuàng)建的Activity都保存在回退堆棧內(nèi),每次后退就將棧頂?shù)腁ctivity取出.
Service
Service是Android提供一個允許長時間留駐后臺的一個組件,最常見的 用法就是做輪詢操作,同時,Service提供跨進(jìn)程通信組件葫隙!
Service生命周期
StartService啟動Service
①首次啟動會創(chuàng)建一個Service實(shí)例,依次調(diào)用onCreate()和onStartCommand()方法,此時Service 進(jìn)入運(yùn)行狀態(tài),如果再次調(diào)用StartService啟動Service,將不會再創(chuàng)建新的Service對象, 系統(tǒng)會直接復(fù)用前面創(chuàng)建的Service對象,調(diào)用它的onStartCommand()方法栽烂!
②但這樣的Service與它的調(diào)用者無必然的聯(lián)系,就是說當(dāng)調(diào)用者結(jié)束了自己的生命周期, 但是只要不調(diào)用stopService,那么Service還是會繼續(xù)運(yùn)行的!
③無論啟動了多少次Service,只需調(diào)用一次StopService即可停掉Service
BindService啟動Service
①當(dāng)首次使用bindService綁定一個Service時,系統(tǒng)會實(shí)例化一個Service實(shí)例,并調(diào)用其onCreate()和onBind()方法,然后調(diào)用者就可以通過IBinder和Service進(jìn)行交互了,此后如果再次使用bindService綁定Service,系統(tǒng)不會創(chuàng)建新的Sevice實(shí)例,也不會再調(diào)用onBind()方法,只會直接把IBinder對象傳遞給其他后來增加的客戶端!
②如果我們解除與服務(wù)的綁定,只需調(diào)用unbindService(),此時onUnbind和onDestory方法將會被調(diào)用!這是一個客戶端的情況,假如是多個客戶端綁定同一個Service的話,情況如下 當(dāng)一個客戶完成和service之間的互動后,它調(diào)用 unbindService() 方法來解除綁定恋脚。當(dāng)所有的客戶端都和service解除綁定后腺办,系統(tǒng)會銷毀service。(除非service也被startService()方法開啟)
③另外,和上面那張情況不同,bindService模式下的Service是與調(diào)用者相互關(guān)聯(lián)的,可以理解為 "一條繩子上的螞蚱",要死一起死,在bindService后,一旦調(diào)用者銷毀,那么Service也立即終止!
通過BindService調(diào)用Service時調(diào)用的Context的bindService的解析 bindService(Intent Service,ServiceConnection conn,int flags)
service:通過該intent指定要啟動的Service
conn:ServiceConnection對象,用戶監(jiān)聽訪問者與Service間的連接情況, 連接成功回調(diào)該對象中的onServiceConnected(ComponentName,IBinder)方法; 如果Service所在的宿主由于異常終止或者其他原因終止,導(dǎo)致Service與訪問者間斷開 連接時調(diào)用onServiceDisconnected(CompanentName)方法,主動通過unBindService() 方法斷開并不會調(diào)用上述方法!
flags:指定綁定時是否自動創(chuàng)建Service(如果Service還未創(chuàng)建), 參數(shù)可以是0(不自動創(chuàng)建),BIND_AUTO_CREATE(自動創(chuàng)建)
StartService啟動Service后bindService綁定
如果Service已經(jīng)由某個客戶端通過StartService()啟動,接下來由其他客戶端 再調(diào)用bindService()綁定到該Service后調(diào)用unbindService()解除綁定最后在 調(diào)用bindService()綁定到Service的話,此時所觸發(fā)的生命周期方法如下:
onCreate( )->onStartCommand( )->onBind( )->onUnbind( )->onRebind( )
PS:前提是:onUnbind()方法返回true!!! 這里或許部分讀者有疑惑了,調(diào)用了unbindService后Service不是應(yīng)該調(diào)用 onDistory()方法么!其實(shí)這是因?yàn)檫@個Service是由我們的StartService來啟動的 ,所以你調(diào)用onUnbind()方法取消綁定,Service也是不會終止的!
得出的結(jié)論: 假如我們使用bindService來綁定一個啟動的Service,注意是已經(jīng)啟動的Service!!! 系統(tǒng)只是將Service的內(nèi)部IBinder對象傳遞給Activity,并不會將Service的生命周期 與Activity綁定,因此調(diào)用unBindService( )方法取消綁定時,Service也不會被銷毀糟描!
IntentService
IntentService是繼承與Service并處理異步請求的一個類,在IntentService中有 一個工作線程來處理耗時操作,請求的Intent記錄會加入隊(duì)列
當(dāng)需要有耗時的操作,就放在后臺進(jìn)行,此時需要使用IntentService(總結(jié))
客戶端通過startService(Intent)來啟動IntentService; 我們并不需要手動地區(qū)控制IntentService,當(dāng)任務(wù)執(zhí)行完后,IntentService會自動停止; 可以啟動IntentService多次,每個耗時操作會以工作隊(duì)列的方式在IntentService的 onHandleIntent回調(diào)方法中執(zhí)行,并且每次只會執(zhí)行一個工作線程,執(zhí)行完一怀喉,再到二這樣!
Binder
Binder用來實(shí)現(xiàn)Android跨進(jìn)程通信的一種機(jī)制,也是Android程序中的一個類.
Binder流程:
BroadcastReceiver
廣播,相當(dāng)于一個全局的事件監(jiān)聽器和消息發(fā)送器.
ContentProvider
自定義ContentProvider
通過ContentObserver監(jiān)聽ContentProvider的數(shù)據(jù)變化
Intent
1.顯式Intent與隱式Intent的區(qū)別
- 顯式Intent:通過組件名指定啟動的目標(biāo)組件,比如startActivity(new Intent(A.this,B.class)); 每次啟動的組件只有一個~
- 隱式顯式Intent:不指定組件名,而指定Intent的Action,Data,或Category,當(dāng)我們啟動組件時, 會去匹配AndroidManifest.xml相關(guān)組件的Intent-filter,逐一匹配出滿足屬性的組件,當(dāng)不止一個滿足時, 會彈出一個讓我們選擇啟動哪個的對話框~
2.Intent的七個屬性
-
ComponentName
2)Action
3)Category
-
Data,Type
5)Extras
6)Flags
3 隱式Intent
數(shù)據(jù)讀寫
文件操作模式
SharedPreferences保存用戶偏好參數(shù)
筆記來源: w3cschool、簡書船响、CSDN