Android快速入門
1. 搭建開發環境
>解壓壓縮文件,得到:①Android SDK (類似於JDK)② Eclipse ③ADT
>配置兩個path環境變量:D:\adt-bundle-windows-x86\sdk\platform-tools;D:\adt-bundle-windows-x86\sdk\tools
>配置基本的Eclipse的設置:
調整字體大小,字符集,配置android sdk的位置
>創建模擬器:
2. 創建第一個Android項目: HelloAndroid
next-next-next-Empty Activity-next-finish
打開應用程序的AndroidManifest.xml文件,修改minsdkVersion值為8.
3. 四個文件目錄結構:
1). 應用項目的
>L01_HelloWorld:指明當前工程的名稱
>src:存放我們編寫的java代碼
>XxxActivity:一個XxxActivity對應著一個可以與用戶交互的應用程序的界面。
>繼承於Activity
>重寫onCreate()方法。在方法內:
super .onCreate(savedInstanceState); 調用父類的此方法,進行必要的初始化操作
setContentView(R.layout. activity_main); 加載布局文件
>gen : 系統自動生成的文件目錄。裡面包含著以應用程序包名命名的一個包 ,包含著R.java
>R類:實際上代表著res文件目錄,通過R類,可以實現代碼和應用程序之間的調用。
R類的內部結構是系統自動生成的,一般我們不去操作
>assets:資產目錄
>bin:編譯以後的classes.dex 文件,apk文件都保存在此目錄下
>libs:存放第三方的jar包
res:全稱:resource:資源,代表著當前應用程序的資源目錄。內部保存著layout/drawable / values-strings/values-style
>drawable-xxx:提供了不同分辨率的圖片,供不同分辨率的手機所使用。
>layout:布局文件。對應著每一個應用程序界面的布局,布局文件就聲明在此文件目錄下。
文件都是xml格式
>values-strings.xml:聲明當前應用程序需要的字符串數據。可以在功能清單文件和布局文件中使用
>values-style.xml:當前應用程序的樣式和主題都聲明在此
AndroidManifest.xml:功能清單文件。類似於web工程中的web.xml文件
>指明當前應用程序的包名、可以適配的sdk的最低版本、當前應用程序的版本號、權限
:指明當前應用程序的名稱label,圖標icon,主題Theme
對應著一個用戶界面的Activity。每一個應用程序的Activity的子類,都需要在此功能清單文件中注冊。
可以聲明屬性:name /label /theme / launchmode
< intent-filter>
< action android:name ="android.intent.action.MAIN" />
< category android:name ="android.intent.category.LAUNCHER" />
此處的intent-filter的作用:
action:當前的action的值指明了當前的Activity是當前應用的主界面
category:使得當前的應用程序可以顯示在系統的桌面應用中
2). 應用APK的
3). Android系統的
4). SDK的
4. 三個應用開發工具
1). ADB: 調試工具
2). DDMS: eclipse中的debug調試工具:
3). Log: 日志工具類
5. 尺寸
結論:
1.如果給視圖組件設置具體的長度或者寬度時,我們要選擇使用dp為單位,而不要選擇px為單位。
2.如果設置視圖組件的字體的大小,我們選擇sp,而不用dp.
6.關於顏色
關於顏色的設置: RGB : red green blue :范圍00~ff
紅色:#ff0000
綠色:#00ff00
藍色:#0000ff
白色:#ffffff
黑色:#000000
7. 相關API:
8. 應用練習:
完成步驟:
1.創建一個安卓工程,修改AndroidManifest.xml中的minsdkVersion.
2.完成布局文件:xxx.xml文件。
3.完成業務邏輯:
1)在XxxActivity的onCreate方法中加載布局文件:setContentView(R.layout.xxx);
2)獲取界面上對應的視圖對象: findViewById(R.id.xxx)
3)在試圖對象上綁定指定的監聽器: button.setOnClickListener(listener);
必須重寫監聽器的抽象方法: onClick()
補充:
模擬器經常掉線,可以考慮的修改措施:
第1層次:reset adb
第2層次:將掉線的模擬器關閉,重新開啟
第3層次:關閉掉線的模擬器,關閉eclipse,打開任務管理器將adb.exe進程刪掉。然後重啟Eclipse和模擬器
02_四大應用組件之Actvity
1. Activity的理解:
2. Intent的理解
關於IntentFilter
3. Intent的使用:(創建、攜帶數據、讀取數據)
1.創建:
顯式意圖: Intent intent = new Intent(Context context,Class clazz);
隱式意圖:Intent intent = new Intent(String action);
2.攜帶數據:
intent.putExtra(String key,Xxx value)
intent.setData(Uri uri);
3.讀取數據:
intent.getXxxExtra(String key);
在Intent內部維護了一個HashMap
4. Activity的使用:(聲明、啟動、結束)
1.聲明(如何創建一個Activity)
①創建一個繼承於Activity的子類
②在AndroidManifest.xml文件中注冊此組件。
③在res-layout-提供一個布局文件:xxx.xml
④ 在Activity的子類中重寫的onCreate()中加載布局文件:setContentView(R.layout.xxx);
2.啟動:
一般啟動: startActivity(Intent intent)
帶回調的啟動: startActivityForResult(int requestCode,Intent intent)
>接收回調數據的回調方法:onActivityResult( int requestCode, int resultCode, Intent data)
3.結束:
一般結束:finish();
帶結果的結果:setResult(int resultCode ,Intent intent);
finish();
5. Activity的生命周期
6. TaskStack和lauchMode
TaskStack任務棧結構:
關於Activity的啟動模式:LaunchMode
在AndroidManifest.xml中的的屬性中設置啟動模式。
- 總結:設置監聽的四種方式:
以給Button設置點擊的監聽為例:
方式一:提供一個接口的匿名實現類的匿名對象
btn.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
//點擊button需要完成的操作
}
});
方式二:
btn.setOnClickListener(this);
接著需要當前的Activity實現View.OnClickListener接口,需要當前的Activity重寫onClick(View v){}
方式三:
在布局文件中,聲明
回到布局文件對應的Activity中,提供一個方法:public void call(View v){ }
方式四:提供一個接口的匿名實現類的對象
在當前的Activity中聲明一個屬性:
private View listener = newView.OnClickListener(){
public void onClick(View v){
//點擊button需要完成的操作
}
};
然後
btn.setOnClickListener(listener);
——————————————————————————————————
考慮一下回調方法的參數的判斷:
方式一:
if(v == btn1){
}else if(v == btn2){
}...
方式二:
switch(v.getId()){ //byte short char int String 枚舉
case R.id.btn1:
break;
case R.id.btn2:
break;
....
}
7. 應用練習:打電話與發短信
1). 功能描述:
1) 點擊”打電話”: 進入撥號界面
2) 長按”打電話”: 直接撥打電話
3) 點擊”發短信”: 進入編輯短信界面
_____________________________________________
4) 長按”發短信”: 直接將短信發送出去
2). 技術點:
① 布局的搭建。在ViewGroup中還可以嵌套ViewGroup
② 給必要的視圖對象設置點擊或長按的監聽事件
③ 如何在當前應用中調用其它應用。 需要使用隱式意圖。
④ 數據的攜帶。putExtra(String key,Xxx value) (--->Xxx getXxxExtra(String key)) ,setData(Uri uri);
⑤ 權限的聲明:需要在功能清單文件中,設置當前應用的權限。
3). 總結:
1). 實現一個簡單功能的應用的步驟:
①創建一個應用,修改一下minsdkVersion
②完成布局的搭建
③回到Activity中,加載布局文件:setContentView(R.layout.xxx)
④獲取並初始化視圖對象 並對必要的視圖對象設置監聽
⑤完成監聽需要做的相應的功能
2). 使用隱式意圖啟動系統應用的界面
首先打開要啟動的某一個應用的界面A,通過logcat,使用ActivityManager進行過濾,查看打開的當前界面的信息:當前的Activity類以及所聲明的包名。
其次,找到應用程序的源碼,在其功能清單文件中,搜索當前的Activity,找到其聲明的中的action。
最後,在需要通過某個界面啟動A的界面中,創建一個隱式意圖,使用找到的action。啟動一個新的Activity即可。
3). 權限:
03_用戶界面(上)
1.UI的理解
繼承樹結構:
2.UI事件的理解
3.常用的UI組件3.1. 簡單UI組件
1). TextView : 文本視圖
2). EditText : 可編輯的文本視圖
3). Button : 按鈕
4). ImageView : 圖片視圖
5). CheckBox : 多選框
6). RadioGroup/RadioButton : 單選框
3.2. 菜單Menu
* 1.如何觸發Menu的顯示?
* >OptionMenu:通過menu鍵觸發
*
*
* >ContextMenu:通過長按某一個視圖對象觸發。
* 需要給視圖綁定一個監聽器:setOnCreateContextMenuListener(listener)
*
* 2.如何向Menu中添加MenuItem?
*
* >OptionMenu:
* 方式一:在onCreateOptionsMenu()方法中通過menu.add()方式添加
* 方式二:在res-menu下提供menu的
xml文件,在onCreateOptionsMenu()加載
xml文件
* >ContextMenu:
* 方式一:在onCreateContextMenu()方法中通過menu.add()方式添加
* 方式二:在res-menu下提供menu的
xml文件,在onCreateContextMenu()加載
xml文件
*
* 3.選擇某個MenuItem時如何響應?
*
* >OptionMenu:
* 在onOptionsItemSelected()方法中處理選中的item
*
* >ContextMenu:
* 在onContextItemSelected()方法中處理選中的item
3.3. 進度條
1). ProgressBar
a. 圓形
b. 水平
2). SeekBar
從代碼角度,設置view的可見性:
3.4. 對話框
1). API結構
2). AlertDialog
a. 一般的
方法鏈的的使用:
new AlertDialog.Builder(this)
.setTitle("")
.setMessage("")
.setPositiveButton("確定",listener)
.setNegativeButton("取消",listener)
.show();
//自動的dismiss.
b.帶單選列表的
new AlertDialog.Builder( this)
.setTitle( "請選擇背景顏色" )
. setSingleChoiceItems( String[] arr,listener)
.show();
//需要手動的dismiss.
c.自定義布局的
//1.創建對應指定布局文件的View對象
final View view = View.inflate (this , R.layout.dialog_login , null);
//2.將view填充到AlertDialog中
new AlertDialog.Builder( this)
.setView(view)
.setPositiveButton( "確認" ,listener)
.setNegativeButton("取消",null)
.show();
3). ProgressDialog
a. 圓形進度
final ProgressDialog dialog = ProgressDialog.
show(
this, "數據加載" ,"數據正在加載..." );
//創建一個分線程(繼承的方式)
new Thread(){
public void run() {
//停留3秒鐘
try {
Thread.
sleep(3000);
}
catch (InterruptedException e) {
//
TODO Auto-generated catch block
e.printStackTrace();
}
//使得當前的dialog消失
dialog.dismiss();
}
}.start();
b. 水平進度
//創建一個ProgressDialog
final ProgressDialog dialog =
new ProgressDialog(
this );
//設置其為水平的格式
dialog.setProgressStyle(ProgressDialog.
STYLE_HORIZONTAL);
//顯示
dialog.show();
//創建一個分線程,模擬數據的下載(實現的方式)
new Thread(
new Runnable(){
@Override
public void run() {
int count = 200;
//設置dialog的最大值
dialog.setMax(count);
//模擬數據的下載
for(
int i = 0;i < count;i++){
//方式一:
//dialog.setProgress(dialog.getProgress() + 1);
//方式二:
dialog.incrementProgressBy(1);
try {
Thread.
sleep(10);
}
catch (InterruptedException e) {
//
TODO Auto-generated catch block
e.printStackTrace();
}
}
//設置dialog消失
dialog.dismiss();
}
}).start();
4). DatePickerDialog 和 TimePickerDialog
補充:
1). 啟動分線程
2).
根據id查找View對象:findViewById(int id)
>this.findViewById(int id):this代表當前的Activity對象。實際上是在Activity所加載的布局文件中找指定id的視圖組件。
>XxxActivity.this.findViewById(int id):通常使用在Activity的內部類中,表示調用的是外部類XxxActivity所對應的布局文件中find指定的id的視圖對象
>view.findViewById(int id):在指定的view所對應的布局文件中查找指定的id的視圖對象
view的創建方式:View view = View.inflate(this,R.layout.xxx,null);
3). 更新視圖
vcj0="#D4DDE5" border="0" width="100%">
03_用戶界面(下)
3.常用的UI布局(三種)
?線性布局: 用來控制其子View以水平或垂直方式展開顯示
?相對布局: 用來控制其子View以相對定位的方式進行布局顯示
幀布局:中的每一個子View都代表一個畫面,默認以屏幕左上角作為( 0,0 )坐標,按定義的先後順序依次逐屏顯示 , 後面出現的會覆蓋前面的畫面
4.常用的視圖標簽的屬性
1). 視圖的常用屬性
layout_gravity(對外):在子view中聲明此屬性,指明此子view相對於父視圖的相對位置
gravity(對內):①使用在EditText或者TextView中,指明其內部的文本內容當對於自己的位置
②在父視圖中使用此屬性,表明其內部的子view相對於自己的位置
2). 只針對RelativeLayout
針對於兄弟視圖之間:
與父視圖之間:
3). 只針對LinearLayout
1.orientation(方向) horizontal (水平方向)/ vertical(垂直方向)
2.layout_weight(權重) 我們可以設置不同子view在父View中的權重。
5.ListView的使用
1). 理解
分類:簡單視圖列表 和 復雜視圖列表
繼承結構:
2). 使用
a. ArrayAdapter : 顯示簡單文本列表
b. SimpleAdpater :顯示復雜列表
c. BaseAdpater(抽象的父類): 顯示復雜列表
//如何將集合中指定位置的數據裝配到指定的position位置的item裡面
@Override
public View getView(
int position, View convertView, ViewGroup parent) {
//Log.e("TAG", "getView() position:" + position + ",convertView :" + convertView);
if(convertView ==
null){
//創建item布局對應的View對象
convertView = View.
inflate(BaseAdapterActivity.
this, R.layout.
item_ba,
null);
Log.
e("TAG", "創建新的view對象。position : " + position);
}
else{
Log.
e("TAG", "復用現有的view對象。position : " + position);
}
//從View對象中取出需要裝配數據的結構
ImageView iv_ba_icon= (ImageView) convertView.findViewById(R.id.
iv_ba_icon );
TextView tv_ba_name = (TextView) convertView.findViewById(R.id.
tv_ba_name );
TextView tv_ba_content = (TextView) convertView.findViewById(R.id.
tv_ba_content );
//從集合中取出指定位置的數據
FoodInfo foodInfo = data.get(position);
//裝配數據
iv_ba_icon.setImageResource(foodInfo.getIcon());
tv_ba_name.setText(foodInfo.getName());
tv_ba_content.setText(foodInfo.getContent());
return convertView;
}
3). 給ListView的Item設置監聽
//給ListView設置點擊的監聽事件
lv_main.setOnItemClickListener(
listener);
//給ListView設置長按的監聽事件
lv_main.setOnItemLongClickListener(
listener );
4). ListView的優化(第一層次)
ListView的優化主要針對的就是getView()方法的優化
getView()的作用:如何將集合中指定位置的數據裝配到指定的position位置的item裡面
優化前:如果當前的ListView一共需要顯示1萬條數據,那麼當每次調用getView()方法時,都會創建一個View對象。效率是比較低的。
優化:假設屏幕上初始化時能顯示10個item項,那麼屏幕上最多可以顯示11個item項。
優化以後,我們只需要最多創建11個View對象即可。後需要顯示的view復用已經創建好的View對象。
6. style和Theme
樣式:Style
主題:Theme
7. 練習
1.技術點:
1) ListView (或GridView) + Adapter (ArrayAdapter/SimpleAdapter/ BaseAdapter) + data (集合、數組) + Item Layout
2) 涉及ListView的優化,即getView()方法的優化
3) Adapter通過將內存中的數據進行裝配,顯示在ListView中。
內存中的數據是如何獲取的?① 直接在代碼中寫明。 ② 通過指定的方法,調用本地文件 ③通過聯網獲取數據
4)ArrayAdapter處理的是List
或 T[]類型的數據
SimpleAdapter處理的是List
BaseAdapter處理的是List
5)給ListView設置監聽
04_數據存儲(上)
1.Android中的數據存儲方式:(五種)
2. SharedPrefrence存儲
1). 位置
data/data/應用的包名/shared-prefs/xxx.xml中
2).特點
* 1.存儲的都是一些小的變量。
* 類型為:boolean float
int long String
* 2. 存儲的是鍵值對特點的數據。而且key都為String型,value即為以上的五種類型。
* 要求存儲的數據的key是不相同的。
* 3.隨著應用的卸載而被刪除
4.數據可以設置為私有的,只能被當前應用訪問。
3). 相關API
3. 手機內部文件存儲
1). 位置
data/data/應用的包名/files/xxx
2).特點
* 1.存儲的文件沒有大小的限制。(不能超出存儲空間大小)
* 2.可以存儲任何格式的文件.(.
png .doc .
txt .mp3)
* 3.會隨著應用的卸載被刪除
* 4.可以將此目錄下的文件設置為私有的。
3). 相關API
4. 手機外部文件存儲(sd卡的存儲)
1). 位置
路徑1:storage/sdcard/Android/data/應用的包名/files/xxx
路徑2:storage/sdcard/xxx
2).特點
1.路徑一中保存的數據會隨著應用的卸載被刪除
路徑二中保存的數據不會隨著應用的卸載被刪除
2.存儲在此路徑下的文件是公共的
3.可以存儲任意類型的文件
4.文件的大小沒有限制,只要不超過sd卡的存儲空間即可
5.權限:
android.permission.WRITE_EXTERNAL_STORAGE
3). 相關API
比較內部文件與外部文件存儲?
>文件不大,訪問較為頻繁,比較重要=>手機內部存儲
>數據如果是私有的,不希望其它應用訪問,考慮使用手機內部存儲
>是否需要隨著應用的卸載而被刪除。不需要,使用手機外部存儲的路徑2的方式
應用一:
技術點:
1.GridView + Adapter
2.設置GridView的點擊和長按事件
3.AlertDialog的使用
4.使用SharedPreferences存儲
04_數據存儲(下)
6. 遠程服務器存儲
1).存儲的位置
>存儲在遠程的服務器端
2).特點
>相較於前面的4種存儲方式,遠程服務器的存儲不保存在本地
>不會隨著應用的卸載,而被刪除
3). 實現聯網請求的技術
1) 使用的是Java提供的API:HttpURLConnection
1.要訪問資源的路徑: GET請求: http://192.168.10.165:8080/Web_server/index.jsp?username=Tom&age=10
POST請求:http://192.168.10.165:8080/Web_server/index.jsp
2. URL url = new URL(path)
3.獲取連接對象: HttpURLConnection conn = url.openConnection();
4.設置參數: conn.setConnectionTimeout(); conn.setReadTimeout(); 請求方法:setRequestMethod(); setDoInput();setDoOutput()
如果是POST請求,需要填充請求參數:
conn.getOutputStream().write(byte[]);
5.連接: conn.connect();
6.獲取響應碼: conn.getResponseCode() == 200 404 500
7.獲取服務器端發送過來的數據: conn.getInputStream() BitmapFactory.decode(InputStream is)
8.資源的關閉:流的關閉,連接的關閉:conn.disconnect();
2) android內置的API:HttpClient
1.創建了一個客戶端的對象: DefaultHttpClient
2.設置請求參數: HttpConnectionParams
3.提供一個GET請求的對象/ POST請求的對象: (包含請求路徑)
GET請求: http://192.168.10.165:8080/Web_server/index.jsp?username=Tom&age=10
POST請求:http://192.168.10.165:8080/Web_server/index.jsp
GET請求: new HttpGet(path)
POST請求: new HttpPost(path); 設置請求體: httpPost.setEntity();
4. 得到HttpResponse : client.execute(httpGet/ httpPost)
5. 獲取響應狀態行中的響應碼:httpResponse.getStatusLine() .getStatusCode()
6. 獲取包含響應數據的entity : httpResponse.getEntity()
7. 解析數據: EntityUtils.toString(entity,charset)
8. 使用響應數據
9.資源的關閉: client.getConnectionManager.shutDown();
3 ) 第三方框架:Volley / XUtils
1. 創建一個RequestQueue (先進先出的特點)
2. 創建請求對象: StringRequest/JsonRequest/ImageRequest (重寫 onResponse(String result ) / onErrorResponse())
如果是一個POST請求,還需要重寫getParams(),返回一個包含請求數據的map即可。
3.將請求對象添加到隊列裡: queue.add(request);
4).HTTP協議:
5).搭建服務器端
1.解壓Tomcat服務器,放在指定的路徑下
2.配置環境變量(3個:path/JAVA_HOME/CATALINA_HOME)
3.如何在Eclipse中配置Tomcat的鏡像
4.創建一個動態的web工程(Servlet / jsp / .html)
5.在服務器端部署web工程
6.測試:通過浏覽器,可以訪問已經部署好的web工程。 http://192.168.10.165:8080/Web_Project/LoginServlet?username=Tom&age=10
6).實現聯網請求功能的3步:
第1步:主線程:顯示提示列表
第2步:分線程:聯網下載數據
第3步:主線程:更新視圖
模板:
new Thread(){
public void run(){
第2步:分線程聯網下載數據的操作
runOnUiThread(new Runnable(){
public void run(){
//第3步
}
});
}
}.start();
應用練習:
技術點:
1. 顯示一個水平的ProgressDialog:如何創建,如何設置最大值(setMax()),如何讓進度條增長( setProgress(getProgress() + len) /incrementProgressBy(len) ),消失(dismiss())
2.能夠創建指定目錄下的一個文件。(存儲在本地: context.getFilesDir() (路徑:data/data/應用包名/files/.. ) 存儲在sd卡:① context.getExternalFilesDir() (路徑: storage/sdcard/Android/data/應用包名/files/...) ② Environment.getExternalStorageDirectory() (路徑:storage/sdcard/ )
創建一個文件的方式:File file = new File(...., "");
3.使用分線程Thread + runOnUiThread();
4.如何啟動另外一個應用的Activity。
5.權限的使用:
04_數據存儲(中)
5. Sqlite數據庫存儲
1). 路徑
data/data/應用的包名/databases/xxx.db
2). 特點
>保存具有一定結構的數據(如:手機聯系人)
>會隨著應用的卸載被刪除
3). sqlite數據庫的特點
4). 相關API
Web中的JDBC (Java DataBase Connectivity)技術:使用Java程序操作數據庫的一門技術。
Driver(驅動):類似於SQLiteOpenHelper類
Connection(數據庫連接):類似於SqliteDatabase類
PreparedStatement:類似於SqliteDatabase類
ResultSet(結果集):類似於Cursor類
5). Android單元測試
1. 添加配置信息
<uses-libraryandroid:name="android.test.runner" />
</application>
<instrumentationandroid:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.atguigu.t4_storage”/>
2. 編寫測試類
class StudentTest extends
AndroidTestCase
6). 練習總結
技術點:
1.布局的設計:ListView + LinearLayout (權重:weight)
2.數據庫的使用: SQLiteOpenHelper + SqliteDatabase + Cursor 結構實現對數據庫的CRUD(增、刪、改、查)操作。
將CRUD的相關操作封裝在BlackNumberDAO類中
3.Android單元測試的使用
4.數據的顯示:實際上調用的就是BlackNumberDAO類中的查詢操作,將查詢到的數據保存在List
中,使用
Adapter進行裝配
5.對於ContextMenu 和 AlertDialog的使用
6.對黑名單數據的添加、修改、刪除:①一方面需要對數據庫中的數據進行操作 (持久化的) ② 另一方面對內存中的集合數據進行更新
注意點: 確定具體的黑名單號碼時,要區分:position 和 BlackNumber的屬性id 以及數據表中的主鍵:_id。
05_消息機制與異步任務
1. 消息機制的引入
如何實現線程間通信呢? (分線程如何傳送數據給主線程)
方式一: Thread + runOnUiThead()
方式二: Thread + Handler + Message
方式三: AsyncTask (實現了對Thread 和 Handler的封裝,提供了一個線程池)
2.Message的使用 :
1).作用
?可理解為線程間通訊的數據單元, 可通過message攜帶需要的數據
2). 對象的創建
調用Message的靜態方法obtain()獲取Message的一個對象。
(Message內部維護了一個消息池,對象是從消息池中獲取的:可能是已經存在的message對象,也可能是新創建的)
3). 對象的使用
int what: 唯一的標識此message對象
int args1/args2:用於存儲int型的數據
Object obj:用於存儲object類型的數據
其它:
long when :此消息要被處理的時間
Message next: 如果在一個message中又聲明另一個message,整體就構成一個對列的結構
Handler target: 處理此Message的Handler對象
Runnable callback: 每個message,都可以設置自己被處理的方式
Message sPool: 涉及到消息池的使用
3.Handler的使用 :
1).作用
?Handler是Message的處理器,同時也負責消息的發送和移除的工作
2). 對象的創建 :
直接new: Handler handler = new Handler(){
public void handleMessage(Message msg){}
}
3). 對象的使用:
a. 發送消息
延遲的非空消息:sendMessageDelayed(Message message,long millis)
延遲的空消息: sendEmptyMessageDelayed(int what, long millis);
即時的消息:sendMessage(Message message);
即時的空消息:sendEmptyMessage(int what);
注意:延遲的消息,不是延遲發送,而是延遲處理
b. 處理消息
雖然handleMessage()方法的優先級比較低,但是是我們主要使用的方式。
c. 移除消息
?移除指定what標識的消息:removeMessages(int what)
移除所有未執行的消息: removeCallbacksAndMessages(null)
理解MessageQueue 和 Looper:(大家在編寫代碼時,不會顯示的去使用這兩個類的,但是如果談消息機制的原理,就離不了這兩個類)
4.消息機制的原理
5.AsyncTask的使用
1). 理解
2). 相關API
6.AsyncTask的基本原理
實現聯網請求功能的3步:
第1步:主線程:顯示提示列表 : onPreExecute();
第2步:分線程:聯網下載數據 : doInBackground()
第3步:主線程:更新視圖: onPostExecute()
面試題:同步和異步的區別?
7.Json數據格式和解析
1). json是什麼?
2). json數據格式
3). 如何解析json?
API:
* 1. 將
json格式的字符串{}轉換為Java對象, 使用原生API
2. 將
json格式的字符串[]轉換為Java對象的List, 使用原生API
3. 將
json格式的字符串{}轉換為Java對象, 使用GSON
4. 將
json格式的字符串[]轉換為Java對象的List, 使用GSON
5. 將Java對象轉換為
json字符串{}, 使用GSON
6. 將Java對象的List轉換為
json字符串[], 使用GSON
1-4:將
json格式的字符串(
json對象、
json數組)轉換為java對象、java對象構成的List。 =>通常使用在客戶端
5-6:java對象、java對象構成的List轉換為
json格式的字符串(
json對象、
json數組) =>通常使用在服務器端
*
總結:哪些位置用到了反射?(,面試題)
1.一個ActivityA中啟動另外一個ActivityB時,另外的這個ActivityB對象,就是系統通過反射的方式幫我們創建的
startActivity(new Intent(this,activityB.class)); --ActivityB的全路徑名已經在AndroidManifest.xml中聲明過了
--拓展:進而startService()等相關的要訪問的組件,都是系統幫我們創建的。
2.在使用setContentView(R.layout.activity_main);讓Activity關聯某一個布局文件。
布局文件中涉及到的各個標簽所對應的布局本身和具體的子View的對象,也是系統幫我們自動創建的。
3. new Gson().fromJson(String json,Class clazz); 底層通過反射將json中的相關數據裝配到clazz所對應的運行時類的對象中
8.圖片的三級緩存技術
1.何為圖片的三級緩存
一級緩存:將圖片數據本身保存在內存中:Map
。其中url為加載圖片的路徑
真實開發中,我們使用的LruCache 實現的,帶圖片緩存的自動回收機制。
好處:速度最快,節省流量
二級緩存:將圖片持久化在手機文件中:保存在sd卡內。 context.getExternalFilesDir()
好處:數據可以持久化,節省流量,相較於三級緩存,速度也快
三級緩存:聯網操作,通過指定的url地址,找到服務器端對應的圖片資源並下載顯示
好處:對於一級緩存、二級緩存中沒有的數據,必須聯網
2.如何實現圖片的三級緩存
1)先從一級緩存中去獲取指定url路徑的Bitmap(Bitmap bitmap = map.get(url))
>如果bitmap != null:直接顯示:imageView.setImageBitmap(bitmap);
>如果bitmap == null:相當於一級緩存中沒有。考慮二級緩存
2) 在手機內部指定的路徑下,查看指定的url所對應的file是否存在。
接著使用Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath);
>如果bitmap != null:直接顯示:imageView.setImageBitmap(bitmap);
同時,將bitmap對象保存到一級緩存
>如果bitmap == null:相當於二級緩存中沒有。考慮三級緩存
比如:url : http://192.168.56.1:8080//Web_server/images/f2.jpg
對應的手機內部文件:file : storage/sdcard/Android/data/應用的包名/files/f2.jpg
3) 通過給定的url,聯網獲取指定url對應的圖片,以流的方式將圖片數據下載。
>如果能找到指定url對應的資源:Bitmap bitmap = BitmapFactory.decodeStream(InputStream is)
①顯示:imageView.setImageBitmap(bitmap);
②將圖片緩存到一級緩存、二級緩存中
>如果找不到指定url對應的資源:顯示加載失敗的圖片
3.實現圖片的三級緩存過程中出現的問題 (難點)
1)現象:如果快速滑動到最後:①出現了圖片的閃動問題;②發現中間快速過掉的圖片也加載了,不合理
2)出現的原因:復用了convertView導致的---針對於問題1
因為每一項item都出現過,所有就自然的會去聯網下載數據--針對問題2
3)針對於問題1:判斷convertView是否是被復用了。
4)具體的實施:
1.在getView的時候,給每一個convertView(或者說給每一個imageView)設置一個標簽,
這個標簽值即為當前要加載的圖片的url地址
2.在分線程聯網前,先判斷一下要聯網下載的圖片(url地址)與當前imageView的標簽是否相同。
如果相同,那就聯網下載圖片。
如果不相同,那就取消聯網下載
3.當需要給imageView設置圖片顯示時,判斷當前imageView的標簽 和馬上要顯示的圖片對應的
url地址是否相同。
如果相同,那就將此圖片顯示。
如果不相同,那就不顯示。但是需要將已經下載的圖片緩存起來(一級緩存和二級緩存)。
關於ListView的優化:四層優化
ListView的優化,實際上就是對Adapter中的getView()的優化
1.第一層優化:復用已有的convertView對象,避免了內存的溢出
效率更高
2.問題一:除了上面復用convertView對象以外,從代碼層面還有沒有優化的可能性?
問題二:對於聯網的應用來說,如果包含圖片,那麼每次都需要去聯網下載圖片嗎?
問題三:如果聯網一共獲取了100000條json數據,都需要一次性獲取到嗎?
3.
第二層優化:
針對於問題一,我們可以創建一個ViewHolder類,讓其與convertView關聯起來
第三層優化:
針對於問題二:對於圖片來講,我們使用圖片的三級緩存
第四層優化:
針對於問題三:使用分頁
9. 應用練習
技術點:
1.使用FrameLayout實現組件的重疊
2. ListView + BaseAdatper的使用
3. 聯網的操作: HttpURLConnection HttpClient Volley
4. JSON格式數據的解析
5. 使用異步任務(AsyncTask)實現圖片的下載
6.體會一下聯網的三個步驟
7.圖片的三級緩存的使用
8.關於圖片的閃動問題的解決
9.權限:聯網的權限;寫入sd卡的權限
06_事件機制
1. 提出問題?
?Activity是如何響應對其中的某個視圖的觸控操作呢? ----使用MotionEvent
?Activity是如何響應對手機的按鍵的操作呢?---使用KeyEvent
2. 屏幕觸控(MotionEvent)機制
1).事件類型:
2).事件發生的順序:
注意:?對屏幕的任何一個操作, 系統都會
自動創建一個MotionEvent對象來對應這個操作,記錄用戶行為
3). API:
操作事件:
事件的分發:從外到內:調用Activity的dispatchTouchEvent() --->ViewGroup 的dispatchTouchEvent()--->某個點擊的view
的dispatchTouchEvent()
事件的消費:從裡到外:調用綁定在某個點擊的view對象的監聽器上,調用監聽器的onTouch() ---->調用view對象的onTouchEvent() ---->ViewGroup 的onTouchEvent() --->調用Activity的onTouchEvent()
一旦在消費的過程中,某一個方法返回true,表示消費了此事件。則不再繼續向外傳遞。
4).事件分發和處理流程
3. 按鍵(KeyEvent)機制
1).事件類型
2). API:
注意點:1.正常情況下,當我們長按某一個key時,會調用-onKeyDown() - onKeyDown()- .... - onKeyLongPress() -- onKeyDown()-
... - onKeyUp().
2.我們發現有些按鍵在長按時,並沒有觸發onKeyLongPress()方法,如何實現這個方法的調用:
1)將onKeyDown()方法返回值改為return true
2)在返回之前,調用event.startTracking()
3.一般情況下,針對於KeyEvent來講,也就針對於onKeyUp()進行操作,對返回鍵(KeyEvent. KEYCODE_BACK)設置單次點擊不能退
出應用的操作。
4. 應用練習1)
技術點:
1.通過調用MotionEvent的getRawX() 和 getRawY(),獲取焦點的坐標
2.通過調用View的getLeft() getRight() getTop() getBottom() 方法,獲取具體的界面上的一個view的坐標
3.通過調用View的layout(l,t,r,b)重新給view定位
4.調用子視圖view的getParent()獲取父視圖。
針對於KeyEvent:
1.在onKeyUp()方法中修改返回值,不讓其直接調用:super .onKeyUp(keyCode, event)
2.設置一個boolean型變量:第一次點擊時,修改boolean型變量的值,使其第二次點擊時,調用super .onKeyUp(keyCode, event)
3.發送一個延遲的空消息,將boolean變量修改為最初的值。
4.為了保證不出現內存洩漏的問題,在onDestroy()中,移除所有未處理的消息
07_四大應用組件之Service
0.組件的特征:
1)需要繼承現有的類或者實現現有的接口
2)組件需要在功能清單文件中注冊
3)組件的對象是由系統在一定情況下,自動創建的。
4)往往需要重寫相關的方法,此方法在滿足一定情況下,調用。此方法稱為:回調方法
1. Service的理解:
Service是一個應用組件, 它用來在後台完成一個時間跨度比較大的工作且沒有關聯任何界面
1).
區別Service與Activity?
2).
區別Service與Thread?
2.Service的分類
3.Service的定義
4.Service的啟動與停止
5. Service的生命周期
注意:每次startService都會調用Service的onStartCommand()
針對於綁定的方式,如果onBind()方法返回值非空,則會調用啟動者(比如:activity)
中的ServiceConnection中的onServiceConnected()方法。
6. 遠程Service的使用(AIDL)
1)
2)
對照著ppt實現AIDL的功能即可
7.應用練習
應用一:本地服務
1.使用本地服務,實現在應用對應的Activity銷毀時,音樂文件依然可以播放。同時,當我們再進入操作界面時,此時的
Activity是一個新的對象,但是,我們仍然可以操作之前開啟的服務。
2.這裡我們將音樂播放的功能,在服務裡實現。
應用二:掛斷電話功能
反射的使用:
//1.通過反射獲取系統服務的管理器
Class clazz = Class.forName( "android.os.ServiceManager");
//2.獲取其內部指定的方法
Method method = clazz.getDeclaredMethod( "getService" , String. class);
//3.調用方法:操作電話服務
IBinder iBinder = (IBinder) method.invoke(null ,Context.TELEPHONY_SERVICE );
應用三:實現黑名單電話的自動掛斷
技術點:
1.對來電相應狀態的監聽,我們在服務中實現
2.TelephonyManager 和 PhoneStateListener 的使用
3.手機來電的三種狀態:空閒狀態、響鈴狀態、接通狀態
08_四大應用組件之BroadcastReceiver
1. 理論概述
1). 特點和作用
2).相關API
3). 常見廣播:
2. 發送廣播
3.注冊廣播接收器
4. 應用練習
1. 針對於開機廣播,創建一個開機廣播的接收器。配置action,提供權限
2.一旦開機,對應廣播接收器的onReceive()方法就開始執行。
3.在此回調方法內,設置startService()的方法,開啟黑名單電話攔截的服務
1.針對於來短信這個有序廣播來說,我們創建一個對應的廣播接收器。配置action,提供權限
2.針對於有序廣播來說,設置最高的優先級:Integer.MAX_VALUE
3.一來短信,對應的接收器的onReceive()開始執行,短信的數據就封裝在onReceive()方法形參的intent中
4.從intent中將短信號碼和短信內容取出來。判斷短信號碼是否為黑名單號碼。若是,執行abortBroadcast()方法。
09_四大應用組件之ContentProvider
1. 理解
1). 為會麼要有ContentProvider?
2). ContentProvider是什麼?
2. 相關API:
1). ContentProvider: 內容提供者類
2). ContentResolver: 內容解析器類 :
3).Uri: 包含一個具有一定格式的字符串所對應資源的類
4).
5). ContentUris: 操作uri的工具類
3. 自定義ContentProvider
4. 使用ContentResolver訪問ContentProvider
5. 應用練習
技術點:
1.如何啟動一個帶回調的Activity。 startActivityForResult() ---> setResult() ---->onActivityResult()
2.顯示列表數據: ListView + BaseAdapter + List
(或 List
3.創建ContentResolver,訪問聯系人的ContentProvider.
10_動畫
1. 理解
2. 使用動畫
1). View動畫的分類
2). View動畫的使用
1. 公用功能
2.
如何指定坐標(中心點, 起始點, 目標點)
2.1 java代碼上:
2.2 xml格式:
3). 使用Drawable 動畫
第1步: 在res-drawable目錄下創建相應的xml格式的文件:
第2步:在具體的組件中配置:
第3步:使用具體的button設置監聽的回調方法。在回調方法中:(AnimationDrawable對象只需要提供一個即可)
3. 應用練習
應用一:
技術點:
1.設置圖片為整體布局的background屬性,同時聲明當前Activity的主題:全屏顯示
2.設置旋轉、縮放、透明度動畫的集並作用在LinearLayout上。
3.自定義圓形進度條
4.設置動畫的監聽,在動畫結束的時候啟動一個新的Activity
5.設置不同的Activity之間切換的動畫
6.將系統提供的sample應用:ApiDemos的工程導入eclipse中。
應用二:
1.布局的設置:使用到了FramLayout顯示圖片的疊加
2.如何實現旋轉動畫,同時注意設置repeatCount:設置為無限循環。當掃描完成時,需要清除動畫
3.使用異步任務實現數據的掃描
4.使用Drawable動畫,顯示圖層效果。
11_圖像處理
1. 理解
- 2. 操作圖片
1). 保存和讀取圖片:
>將資源目錄下的圖片加載顯示: iv.setImageResource(R.drawable.xxx);
>將手機內部文件中的某一個圖片文件轉換為內存中的一個Bitmap對象,並顯示:
Bitmap bitmap = BitmapFactory.decodeFile(String fileAbsolutePath);
//手機內部:this.getFileDirs()對應: data/data/應用包名/files/
//手機sd卡路徑1:this.getExternalFilesDirs(null)對應: storage/sdcard/Android/data/應用包名/files/
//手機sd卡路徑2:Environment.getExternalStorageDirectory()對應: storage/sdcard/
File file = new File(路徑,"文件名");
iv.setImageBitmap(bitmap);
>將內存中的bitmap對象保存起來:
bitmap.commpress(....,...,路徑對應的輸出流); //輸出流: new FileOutputStream(file); openFileOutput(" ");
2)使用矩陣:Matrix
2). 自定義圖形
3). 定義多狀態圖形圖片
a. selector+shape
接著在具體的view組件上,以background屬性的方式添加上
b. selector+drawable
4). 9Patch圖片:
a. 理解
b. 制作
>拖拉上和左的線條,用於將圖片分成9個區域。
>默認情況下,只有1區是可以顯示內容的
>拖拉下和右的線條,指定可以顯示內容的區域大小
好處: 保證圖片在放大以後,不失真!
- 3. 自定義圖形(自定義View)
4. 應用練習
技術點:
1. 9patch圖片的制作
2. PopupWindow的創建,加載指定的布局,顯示在指定位置,消失
3. 給ListView設置onScrollListener()
4. 設置PopupWindow顯示的動畫
5. 給視圖對象設置監聽
6. selector + shape的使用
Context
1). 用來做什麼?
a. 操作應用組件
b. 操作視圖對象
c.獲取應用環境全局信息
2). 實現:
Activity : 前台界面
Service : 後台服務
Application : 應用, 全局數據共享的容器
3). 兩種Context對象:
Activity.this : Dialog, 視圖相關的
getApplicationContext() : 如果對象的生命周期長於Activity, 必須用它
ANR
見課件
屏幕橫豎屏切換
1). 如何強制只能橫或豎屏?
2). 如何動態橫或豎屏?