快捷鍵:
提取方法:Ctrl+Alt+M 提取全局變量:Ctrl+Alt+F 搜索類:ctrl+N
斷點調試時,遇到這個 端口號被佔用
Connected to the target VM, address: 'localhost:8610', transport: 'socket'
短視頻
原理:
- 編碼與解碼:視頻壓縮成文件還原成幀圖像,h264。
- 封裝格式
- 硬解碼(gpu)、軟解碼(cpu)、多線程解碼
- 關鍵幀:視頻壓縮當中比較重要的圖像幀數據
Raw文件夾:一般大文件都存放在Raw和assets文件夾
Bundle的概念:Bundle類型的數據與Map類型的數據相似,都是以key-value的形式存儲數據的
界面跳轉:intent-fiter和Intent
Intent中文意思指“意圖”,通常Intent的隱式啓動和intent-filter連用,顯示啓動不需要intent_filter。
IOC原理:控制反轉 https://www.jianshu.com/p/f96391af0357
觀察者設計模式:觀察者與被觀察者 (以VideoView demo舉例,觀察者是界面,被觀察者就是播放器)
Handler原理圖:
setContentView原理:把自定義Layout加入id爲content的ViewGroup裏
findViewById:根據xml id值來映射成view對象
VideoView:對MediaPlayer的一層封裝,只支持3gp和mp4格式的播放。
清單文件:權限 、四大組件、PMS(Package Manager Service)安全檢查
VideoView全屏:videoView會根據視頻大小來改變自身的大小,所以要自定義view。
style自定義屬性的複用
Android中View和ViewGroup是組合設計模式之一(共23種)
自定義view的幾種方式:
1.繼承View完全自定義
對於繼承View類的自定義控件來說,核心的步驟分別爲尺寸測量與繪製,對應的函數爲onMeasure、onDraw,這是因爲View的子空間是視圖樹的葉子節點,不需要佈局(針對爲什麼佈局開發時有actionBar,但運行後app播放器仍然充滿屏幕)
小技巧:查找類【Ctrl+N】
TextView類中
2.繼承現有控件實現特定效果
3.繼承ViewGroup實現佈局類
這種方式主要用於自定義子視圖的排列方式時,比如下拉刷新,上拉加載等。
ViewGroup具有容器作用:因爲實現了兩個接口ViewParent和ViewManager,其中後者定義了addView及removeView等對子視圖操作的方法,重點實現onLayout方法,這個方法主要是用於子視圖的排放。
public class FrameLayout extends ViewGroup 該類下有onLayout方法
EXACTLY模式
該類爲精確模式。何時使用:
當我們將layout_width or layout_height 設置爲具體數值時,如100dp或是match_parent,這是系統就是調用精確模式。
AT_MOST
最大值模式,當我們將layout_width or layout_height設置爲wrap content時,系統調用的就是這個模式
此時的控件大小是隨着子控件或者內容的變化而變化,只有不超出父控件允許的最大範圍即可
UNSPECIFIED
只有在自定義控件時用到,沒有具體的測量,view自己想要多大有多大
自定義計時器:用Handler的消息機制做數據的減法操作
TextView:
自定義Shape:不自定義可以使用圖片,自定義shape用xml代碼實現
顏色色值:#ffffffff由#加八位數字或字母組成,前兩個ff爲透明度(十六進制),後面六位ffffff爲顏色代碼,採用RGB配色(十六進制)
透明度參照表:
00%=FF(不透明) | 5%=F2 | 10%=E5 | 15%=D8 | 20%=CC |
25%=BF | 30%=B2 | 35%=A5 | 40%=99 | 45%=8c |
50%=7F | 55%=72 | 60%=66 | 65%=59 | 70%=4c |
75%=3F | 80%=33 | 85%=21 | 90%=19 |
95%=0c 100%=00 (全透明) |
解決硬編碼:把代碼裏面的中文字提出到String.xml文件,一些常量可單獨提出到常量類裏面,注意未來界面整潔,維護,規範
dp px sp 之間的概念
px:像素單位 dp:安卓距離單位 sp:安卓字體大小單位
密度 | ldpi | mdpi | hdpi | xhdpi | xxhdpi |
密度值 | 120 | 160 | 240 | 320 | 480 |
代表分辨率 | 240*320 | 320*480 | 480*800 | 720*1280 | 1080*1920 |
當屏幕爲mdpi時,1dp=1px,換算單位爲dp=(dpi/160)px
1dp永遠都等於1sp
Bundle的概念:Bundle 類型的數據與Map類型的數據相似,都是以key-value的形式存儲數據的
界面跳轉:intent-filter和Intent
Handler原理:
線程之間的通信(子線程處理一些結果,通過handler發送到主線程,主線程通過一些方法“handleMessage()”來獲得數據)
死循環不會卡死:
這裏涉及到Linux pipe/epoll機制,簡單來說就是在主線程的messageQueue沒消息時,便阻塞在loop的queue.next()中的nativePollOnce()方法裏,此時主線程會釋放CPU資源進入休眠狀態,直到下個消息到達或者有事務發生,通過往pipe管道寫端寫入數據來喚醒主線程工作。
斷點調試
注意1!!!
//countDownTime一開始是0,需要在這裏設置傳入time
this.countDownTime = time;
注意2!!!當countDownTime == 0的時候,先把它取消掉,在還在進行onCreate()時,是自動取消Handler
如果說Activity還沒有走完,Handler是否還會繼續存在呢?添加cancel()
注意3!!!所以才需要手動調用一次
onCreate(),onDestory()都是系統調用的
SplashActivity添加
//界面銷燬時,回調
@Override
protected void onDestroy() {
super.onDestroy();
timer.cancel();
}
Handler原理尋找
loop類loop()構造器
往下滑找到Looper()
創建Handler的時候,會去ThreadLocal裏面去取這個Looper,這個Looper的構造方法創建MessageQueue()
爲什麼用ThreadLocal去取,而不是新建一個呢?
這就涉及系統源碼,關於主線程Looper和MessageQueue在app剛啓動的時候就已經創建出來了,它們是在ActivityThread類
快速雙擊shift,搜索ActivityThread.java,它是一個app程序的入口,搜索main(String[] args),一般操作系統都有這麼一個main()
這裏面有一個prepareMainLooper(),就相當於創建了一個Looper,還需要調用一個Looper.loop()
然後拿到個MessageQueue不斷去遍歷
這是個Message類,點進去,它裏面有what,arg1,arg2這些標識
點擊CustomCountDownTimer中post(),調用sendMessageDelayed()
它把Runnable這個對象封成了一個Message,這樣就解釋通了
根據handler原理圖,我們發送一個Runable,實際上我們也封裝了一個Message到消息隊列裏面,在app程序啓動的時候,不斷去循環MessageQueue
它是把Runnable這個對象封裝在MesageQueue的callback這個成員變量裏面。
它定義了一些code,發送不同消息的一些類型,然後去回調處理這個handleMessage
Activity的生命週期:就是通過ActivityThread發送一些消息,處理不同消息類型,去調用Activity的生命週期
上傳至github
首先建立倉庫
commit
push
公司項目多人開發需要建立分支,可參考https://www.cnblogs.com/myqianlan/p/4195994.html
開發的一個分支Feature完成後,再develop合併,經過測試完後,最後master(以及還有從master拉出來hotfix進bug修改發版,拉出Release分支用於打包)