Android 2019最新面試實戰總結

  Android:
  
  今日頭條屏幕適配的原理?
  
  1:首先計算出 density,計算公式:當前設備屏幕總寬度(單位爲像素)/ 設計圖總寬度(單位爲 dp) = densitydensity 的意思就是 1 dp 佔當前設備多少像素計算density 的緣由:在佈局文件中填寫的是什麼單位,最後都會被轉化爲 px,系統就是經過上面的方法,將你在項目中任何地方填寫的單位都轉換爲 px
  
  可是,今日頭條適配方案默認項目中只能以高或寬中的一個做爲基準,來進行適配
  
  簡述Android中的加固和使用平臺?
  
  加固:防止代碼反編譯,提升代碼安全性
  
  加固三方平臺,梆梆安全,360加固,愛加密等
  
  區別:梆梆安全,360加固看不到項目中的類,愛加密看的到Java類,單看不到裏面的方法實現體,效果比前面差一點點
  
  加固的底層原理:第三方加固的應用會生成一個Apk,而後把你的APK讀取出來,在封裝到這個第三方應用的APK裏面.
  
  如何對APK瘦身?
  
  1)使用混淆,
  
  2)開啓shrinkResourse(shrink-收縮),會將沒有用到的圖片變成一個像素點
  
  3)刪除無用的語言資源(刪除國際化文件)
  
  4)對於非透明的大圖,使用JPG(沒有透明度信息),代替PNG格式
  
  5)使用tinypng進行圖片壓縮
  
  6)使用webp圖片格式,進一步壓縮圖片資源
  
  7)使用第三方包時把用到的代碼加到項目中來,避免引用整一個第三方庫
  
  簡述多渠道打包及原理和經常使用操做?
  
  針對每個渠道(應用市場)都生成一個帶有渠道標識的apk文件
  
  原理:用戶下載啓動應用,獲取渠道標識,和設備的惟一標識,並上傳到服務器裏面,服務器這裏就 會根據獲取的記錄,根據渠道號而後判斷是否存在該服務器的表裏面.(打標記,取標記,上傳標記)
  
  1)友盟多渠道打包:在清單文件中定義一個佔位符,在gradle腳本中替換佔位符(會使用到Python)
  
  2)美團打包,在meta-data中建立一個空的文件,以文件名標識渠道,作一個解壓與壓縮的操做,速度會比較快
  
  3)新一代多渠道打包,將渠道標識添加到.apk文件的末尾,並不會對源文件損壞
  
  Android下的數據存儲方式有那些?
  
  1)內部存儲,直接存儲在內部文件中
  
  2)外部存儲,首先要判斷外部存儲條件是否可用,而後進行存儲
  
  3)SP存儲,底層是Xml實現的,以鍵值對形式存儲內部的數據,適宜於輕量級的存儲,存儲的數據類型有,boolean,String,int
  
  4)數據庫存儲,SQlite存儲,輕量級的數據庫,強大的增刪改查功能
  
  5)內容提供者,ContentProvider,將本身願意暴露的一部分數據供外部使用操做
  
  6)網絡存儲,等等
  
  Sharepreference 線程安全問題?
  
  官方文檔明確指出,SharedPreferences不支持多線程,進程也是不安全的
  
  若是想要實現線程安全需從新實現其接口,以下
  
  image
  
  假設在多進程訪問SharePreferences的狀況下,該如何保證進程安全和共享數據?
  
  解決辦法就是:將須要共享數據的字段提出來統一存儲到一個文件中。
  
  Android開發下如何有效進行屏幕適配?
  
  1:機型適配,去一些統計網站諸如友盟,如今叫友盟+去看一下市場上最流行的Android機型,有針對性的切圖
  
  2:屏幕適配,適配主流xhdpi屏幕尺寸,使用relativelayout,linerlayout等佈局,多使用matchparent,wrapcontent,及配合weight,權重處理,
  
  3:還有就是在代碼中,設計到具體尺寸的要使用dp2px的轉換,
  
  4:圖片使用可拉伸.9圖片,imageview使用scaletype縮放;
  
  5:使用權重,等比例,百分比佈局等等
  
  對象序列化:
  
  爲何要序列化?
  
  1)永久性保存對象,保存對象的字節序列到本地文件中;
  
  2)經過序列化對象在網絡中傳遞對象;
  
  3)經過序列化在進程間傳遞對象。
  
  在Android中實現序列化有兩個選擇:一是實現Serializable接口(是JavaSE自己就支持的),一是實現Parcelable接口(是Android特有功能,效率比實現Serializable接口高效,可用於Intent數據傳遞,也能夠用於進程間通訊(IPC))。實現Serializable接口很是簡單,聲明一下就能夠了,而實現Parcelable接口稍微複雜一些,但效率更高,推薦用這種方法提升性能。兩種實現方式依舊是貼url,方便你們快速查詢
  
  兩種序列化相關
  
  既然Google推薦Parcelable這種序列化,在這裏,推薦一鍵生成序列化的插件,
  
  在Android Studio裏面搜索插件,以下圖,寫起序列化(根本不用你寫)那就是一個美滋滋吶~
  
  OkHttp相關?
  
  OkHttp支持同步和異步數據請求,但異步請求是在子線程 (由於原生OkHttp的使用時回調方法是在子線程進行的,要刷新界面還須要用Handler做處理,可使用第三方的okhttp-utils,Okgo等等);
  
  OkHttp裏面封裝了線程池、數據轉換、GZIP壓縮(減小流量的傳輸)、HTTP協議緩存等,
  
  OKHttp優勢---使用GZip壓縮減小傳輸的數據量,緩存(減小重複請求);
  
  失敗重試(若是你的服務有多個IP地址,若是第一次鏈接失敗,OKHttp將使用備用地址)
  
  OKhttp是對http協議的封裝,比較底層,所以拓展性強,便於封裝;
  
  OKhttp基於NIO(JDK1.5,非阻塞式IO)效率更高
  
  ButterKnife相關?
  
  簡介:
  
  一款快速高效的注入框架,節約開發時間減小代碼量(依靠插件動態生成View,點擊事件等等)
  
  優勢:
  
  1.強大的View綁定和Click事件處理功能,簡化代碼,提高開發效率
  
  2.方便的處理Adapter裏的ViewHolder綁定問題
  
  3.運行時不會影響APP效率,使用配置方便
  
  4.代碼清晰,可讀性強
  
  使用經驗:
  
  1.Activity ButterKnife.bind(this);必須在setContentView();以後,且父類bind綁定後,子類不須要再bind
  
  2.Fragment ButterKnife.bind(this, mRootView);
  
  3.屬性佈局不能用private or static 修飾,不然會報錯,(注意權限)
  
  4.setContentView()不能經過註解實現。(其餘的有些註解框架能夠)
  
  原理:利用註解和反射去獲取綁定ViewID,
  
  關於原理詳情可參考筆者的這一篇:Android-定製專屬ButterKnife框架,該文詳細介紹了ButterKnife框架並模仿了一個註解綁定View的框架
  
  Rxjava概念,經常使用操做符及拓展?
  
  簡介:
  
  一款優雅的異步框架,代替以前的AsyncTask / Handler / XXX / …
  
  其強大的操做符和鏈式寫法,線程切換等有助於提升開發效率和快速定位Bug
  
  與Retrofit搭配使用更是有意想不到的效果,
  
  底層原理:觀察者模式
  
  等一些相應的博客
  
  缺點:
  
  1:操做符太多會增長學習成本時間
  
  2:使用很差,容易致使內存泄露(解決方式,推薦Rxlifecycle結合Rxjava,規避內存泄漏風險)
  
  ANR相關
  
  ANR全名Application Not Responding, 也就是"應用無響應". 當操做在一段時間內系統沒法處理時, 系統層面會彈出上圖那樣的ANR對話框.
  
  在Android裏, App的響應能力是由Activity Manager和Window Manager系統服務來監控的. 一般在以下兩種狀況下會彈出ANR對話框:
  
  A) 5s內沒法響應用戶輸入事件(例如鍵盤輸入, 觸摸屏幕等).
  
  B) BroadcastReceiver在10s內沒法結束.
  
  形成以上兩種狀況的首要緣由就是在主線程(UI線程)裏面作了太多的阻塞耗時操做,, 例如文件讀寫, 數據庫讀寫, 網絡查詢等等.
  
  如何分析ANR?
  
  ANR產生時, 系統會生成一個traces.txt的文件放在/data/anr/下. 開發人員可經過adb命令將其導出到本地 ($adb pull data/anr/traces.txt .)經過分析,咱們能夠根據具體的日誌查看Anr緣由( 如: 普通阻塞,CPU滿負荷,內存泄露 )
  
  Android中那些場景是執行在主線程的?
  
  1)Activity生命週期回調都是執行在主線程的.
  
  2)Service默認是執行在主線程的.
  
  3)BroadcastReceiver的onReceive回調是執行在主線程的.
  
  4)沒有使用子線程的looper的Handler的handleMessage, post(Runnable)是執行在主線程的.
  
  5)AsyncTask的回調中除了doInBackground, 其餘都是執行在主線程的.
  
  6)View的post(Runnable)是執行在主線程的.等等
  
  三級緩存:
  
  當咱們第一次打開應用獲取圖片或其它資源時,首先到網絡去下載,而後依次存入內存緩存,磁盤緩存,
  
  當咱們再一次須要用到剛纔下載的這張圖片時,就不須要再重複的到網絡上去下載,直接能夠從內存緩存和磁盤緩存中找,因爲內存緩存速度較快,咱們優先到內存緩存中尋找該圖片,若是找到則運用,
  
  若是沒有找到(內存緩存大小有限),那麼咱們再到磁盤緩存中去找。
  
  只要咱們合理的去協調這三層緩存運用,即可以提高應用性能,給用戶更好的體驗
  
  三級緩存指的是:內存緩存、本地緩存、網絡緩存。其各自的特色是內存緩存速度快, 優先讀取,本地緩存速度其次, 內存沒有該資源信息就去讀取本地內存,網絡緩存速度較慢(比較對象是內存緩存和本地緩存),假設本地內存也沒有,才請求網絡獲取。
  
  內存泄漏:
  
  當應用內部再也不須要某個實例後,可是這個對象卻仍然被引用,這個狀況就叫作內存泄露(Memory Leak)。安卓虛擬機爲每個應用分配必定的內存空間,當內存泄露到達必定的程度就會形成內存溢出。
  
  致使內存泄露常見緣由:
  
  1)靜態變量直接或者間接地引用了Activity對象就會形成內存泄露
  
  2)Activity使用了靜態的View(View會持有Activity的對象的引用)
  
  3)Activity定義了靜態View變量???
  
  4)ImageSpan引用了Activity Context
  
  5)單例中引用了Activity的Context(須要使用Application的Context)
  
  6)對於使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等資源,應該在Activity銷燬時及時關閉或者註銷,不然這些資源將不會被回收,從而形成內存泄漏。
  
  7)靜態集合保存的對象沒有及時消除(不使用的時候置爲null)
  
  8)在Java中,非靜態(匿名)內部類會引用外部類對象,而靜態內部類不會引用外部類對象
  
  9)在Activity中,建立了非靜態內部類(內部類直接或者間接引用了Activity)的靜態成員變量
  
  10)線程包括AsyncTask的使用,Activity退出後線程還在運行(線程在死循環),而且在線程中使用了Activity或view對象(解決方法:不要直接寫死循環,能夠設置一個布爾類型的TAG,當activity推出的時候,設置TAG爲False)
  
  11)Handler對象的使用,Activity退出後Handler仍是有消息須要處理(解決方法:在退出activity以後,移除消息)
  
  12)WebView形成的內存泄漏(在onDestory中銷燬)
  
  如何進行內存泄露分析?
  
  A: 經過Android Studio 窗口進行分析,查看內存分配狀況,若是操做應用是內存一直往上漲說明存在內存泄露
  
  B: 定位內存泄露分析的工具---MAT(Memory Analyzer tool)
  
  C: 使用開源庫LeakCanary快速定位內存泄露
  
  Android中的四大組件相關?
  
  Activity:
  
  Activity是一個應用程序組件,提供一個屏幕(狹義的理解就是當前APP的界面),用戶能夠用來交互爲了完成某項任務。(點擊,登陸,跳轉頁面)
  
  Activity中全部操做都與用戶密切相關,是一個負責與用戶交互的組件,能夠經過setContentView(View)來顯示指定控件(設置佈局文件)。
  
  在一個android應用中,一個Activity一般就是一個單獨的屏幕,它上面能夠顯示一些控件也能夠監聽並處理用戶的事件作出響應。
  
  Activity四種啓動模式?
  
  Activity的啓動模式指,能夠根據實際開發需求爲Activity設置對應的啓動模式,從而能夠避免建立大量重複的Activity等問題。
  
  1)standard
  
  standard爲Activity的默認啓動模式,能夠不用寫配置。在這個模式下,都會默認建立一個新的實例。所以,在這種模式下,能夠有多個相同的實例,也容許多個相同Activity疊加。(點back鍵會依照棧順序依次退出)
  
  2)singleTop
  
  singleTop模式下,Activity能夠有多個實例,可是不容許多個相同Activity疊加。即,若是Activity在棧頂的時候,啓動相同的Activity,不會建立新的實例,而會調用其onNewIntent方法。
  
  3)singleTask
  
  singleTask表示只有一個實例。在同一個應用程序中啓動他的時候,若Activity不存在,則會在當前task建立一個新的實例,若存在,則會把task中在其之上的其它Activity destory掉並調用它的onNewIntent方法。若是是在別的應用程序中啓動它,則會新建一個task,並在該task中啓動這個Activity,singleTask容許別的Activity與其在一個task中共存,也就是說,若是我在這個singleTask的實例中再打開新的Activity,這個新的Activity仍是會在singleTask的實例的task中。
  
  4)singleInstance
  
  只有一個實例,而且這個實例獨立運行在一個task中,這個task只有這個實例,不容許有別的Activity存在。
  
  BraodcastReceiver:(待補充)
  
  使用了設計模式中的觀察者模式:基於消息的發佈/訂閱事件模型。
  
  註冊的方式分爲兩種:靜態註冊、動態註冊
  
  ContentProvider:(待補充)
  
  外界能夠經過ContentResolver接口來訪問ContentProvider(內容提供者)中的數據。Uri 通用資源標誌符(Universal Resource Identifier)Uri表明要操做的數據,Android中可用的每種資源 - 圖像、視頻片斷等均可以用Uri來表示。ContentProvider共享數據是經過定義一個對外開放的統一的接口來實現的。然而,應用程序並不直接調用這些方法,而是使用一個 ContentResolver 對象,調用它的方法做爲替代。ContentResolver能夠與任意內容提供者進行會話,與其合做來對全部相關交互通信進行管理。當外部應用須要對ContentProvider中的數據進行添加、刪除、修改和查詢操做時,可使用ContentResolver類來完成,要獲取ContentResolver對象,可使用Context提供的getContentResolver()方法。
  
  IntentService:
  
  IntentService是Service的子類,比普通的Service增長了額外的功能。IntentService會建立獨立的worker線程來處理全部的Intent請求;會建立獨立的worker線程來處理onHandleIntent()方法實現的代碼,無需處理多線程的問題;全部請求處理完成後,IntentService會自動中止,開發者無需手動調用stopSelf()方法中止Service;
  
  簡述System.exit(0) 、onDestory()、Activity.finish()三者的區別
  
  1)System.exit(0) 是你正常結束程序,kill 掉當前進程,針對的是整個Application
  
  2)onDestory()方法是Activity生命週期的最後一步,資源空間等就被回收了。當從新進入此Activity的時候,必須從新建立,執行onCreate()方法.
  
  3)Activity.finish()當你調用此方法的時候,系統只是將最上面的Activity移出了棧,並無及時的調用onDestory()方法,也就是佔用的資源沒有被及時釋放。
  
  圖片優化,以及圖片加載框架的使用,如Picasso、 Fresco、Glide等?
  
  1)儘可能使用小的圖片,對圖片進行壓縮,bitmapfactory.options圖片配置類,insimplesize進行縮放,設置圖片的編碼方式;對圖片使用軟引用,內存不夠時即時釋圖片內存;對圖片的複用,三級緩存的使用;
  
  即時回收再也不使用的bitmap對象;
  
  2)Picasso,不支持gif,緩存的是Argb8888的原圖,佔用內存較大,圖片的框架使用了OkHttp緩存機制,使用Http協議緩存,也是異步加載.
  
  3)Fresco,框架是FaceBook公司推出的,適合批量加載圖片,底層是經過三級緩存(2級內存,1級磁盤)
  
  加載成功後自動替換成目標圖片
  
  4)glide,Google公司14年推出來的,能夠加載GIF圖,也能夠根據指定圖片清晰度,底層的原理:爲Bitmap維護一個對象池,對象池的目的是經過減小對象的分配,以重用來提升性能.對象池也能夠幫助提升滾動的性能。API簡潔易調用
  
  Handle相關:
  
  Handler 工做流程基本包括 Handler、Looper、Message、MessageQueue 四個部分。但咱們在平常開發中,常常都只會用到 Handler 和 Message 兩個類。Message 負責消息的搭載,裏面有個target用於標記消息,obj用於存放內容,Handler 負責消息的分發和處理。
  
  通常在開發中是怎麼使用 Handler 的?
  
  官方不容許在子線程中更新 UI,因此咱們常常會把須要更新 UI 的消息直接發給處理器 Handler,經過重寫 Handler 的handleMessage()方法進行 UI 的相關操做。
  
  Handle使用中就沒什麼須要注意的嗎?
  
  有,Handler 若是設置爲私有變量的話,Android Studio 會報警告,提示可能會形成內存泄漏,這種狀況能夠經過設置爲靜態內部類 + 弱引用,或者在onDestroy()方法中調用Handler.removeCallbacksAndMessages(null)便可避免
  
  Handler 總體工做流程淺析分爲如下四個步驟:
  
  異步通訊準備 => 消息入隊 => 消息循環 => 消息處理
  
  A:異步通訊準備
  
  I:假定是在主線程建立 Handler,則會直接在主線程中建立處理器對象Looper、消息隊列對象MessageQueue和 Handler 對象。
  
  須要注意的是,Looper和MessageQueue均是屬於其建立線程的。
  
  II:Looper對象的建立通常經過Looper.prepareMainLooper(www.huarenyl.cn)和Looper.prepare()兩個方法,而建立Looper對象的同時,將會自動建立MessageQueue。
  
  III:建立好MessageQueue後,Looper將自動進入消息循環。此時,Handler自動綁定了主線程的Looper和MessageQueue。
  
  B:import { getProps, requestInitialData } from www.yigou521.com"../base";java

function Index(props) {
const [desc, setDesc] = useState(www.hengtongyoule.com"Hello world~");android

//getProps獲取props中的ssrData,重構和服務端渲染時props有值,第三個參數爲默認值
const [data, setData] = useState(getProps(props, "data", ""));程序員

//在單頁面路由頁面跳轉,渲染組件時,requestInitialData調用getInitialProps
requestInitialData(props, Index, { data: setData });
return (<div>{data}<www.gouyiflb.cn/ /div>)
}
Index.getInitialProps = async () => {
let data;
const res = await request.get("/api/getData");
if (!res.errCode) data = res.data;
return {
data
};
};
export default Index;web

如此封裝之後,咱們依然保證了一套代碼能在服務端和客戶端運行,requestInitialData 方法第三個傳入參數,是一個對象,傳入了須要被修改的狀態的 set 方法,最終 getInitialProps 返回數據後,會和傳入的對象對比,屬性名一致便會調用 set 方法進行狀態修改,requestInitialData 是一個 useEffect hook,代碼以下面試

複製代碼
export function requestInitialData(props, component, setFunctions) {
useEffect((www.mhylpt.com) => {
//客戶端運行時
if (typeof window != "undefined") {
//非同構時,而且getInitialProps存在
if (!props.ssrData && component.getInitialProps) {
component.getInitialProps().then(data www.honghgjpt.com=> {
if (data) {
//遍歷結果,執行set賦值
for (let key in setFunctions) {
for (let dataKey in data) {
if (key == dataKey) {
setFunctions[key](data[dataKey]);
  
  工做線程經過Handler發送消息Message到消息隊列MessageQueue中,消息內容通常是 UI 操做。發送消息通常都是經過Handler.sendMessage(Message msg)和Handler.post(Runnabe r)兩個方法來進行的。而入隊通常是經過MessageQueue.enqueueeMessage(Message msg,long when)來處理。
  
  C:消息循環
  
  主要分爲「消息出隊」和「消息分發」兩個步驟,Looper會經過循環取出消息隊列MessageQueue裏面的消息Message,並分發到建立該消息的處理者Handler。若是消息循環過程當中,消息隊列MessageQueue爲空隊列的話,則線程阻塞。
  
  D:消息處理
  
  Handler接收到Looper發來的消息,開始進行處理。
  
  拓展
  
  先簡單介紹下你本身?
  
  分析:除了向面試官作簡單的基本自我介紹以外,還需向面試官展示自身對該職業所必須具有的一些自身特質,
  
  好比,面試程序員職業須要間接的向面試官表示本身思惟嚴謹,對細節的處理,理性思惟,假設論證等等;面試產品等職業,須要向面試官經過本身的一些故事間接展示對產品的見解以及獨特的思惟個性等等
  
  切入點:自身特質可否符合該職位的預期需求
  
  本身的興趣愛好特長有那些?
  
  在企業和麪試官看來,若是求職者的愛好和應聘的崗位在某些方面偏偏有正向關聯,就會有興趣。面試官也會經過應聘者的興趣愛好來判斷其價值觀是否與企業文化契合,可否很好地融入工做團隊。求職者的回答將有可能爲面試加分。
  
  下列興趣愛好所反映出的一些性格和職業方向可供參考:
  
  1.籃球,足球,排球:團隊精神,適用大多數崗位。
  
  2.圍棋,國際象棋:戰略意識,適合市場類或高端職位。
  
  3.閱讀,古典音樂:高雅,適合文職類的職位。
  
  4.旅遊:適應不一樣環境的能力,快速學習的能力,適合銷售業務類職位。
  
  5.舞蹈:外向,易溝通,適合公關、市場類的職位。
  
  對本身的指望和規劃?
  
  分析:職業發展規劃表面上看是在考察你(求職者)、職位、公司三者之間長期的契合程度,但實際上,這麼大的一個問題徹底不是三眼兩語間可以表達清楚的。面試官(不管HR仍是專業部門的)主要是看你回答問題時的思路是否清晰,回答中表現出的工做態度如何,順便看看你是否對公司和職位有足夠的瞭解。因此無論答案如何,最關鍵的就是不能茫然。
  
  切入點:依舊自身特色,對將來指望和規劃需表述清晰,思惟敏捷
  
  談談本身的優勢和缺點?
  
  先談缺點:
  
  技術行業面試基本是由該崗位將來同事和上司進行。這種面試技術性強,行爲問題主要考察就是你是否真心想作這個工做(而不是當跳板或者據說高薪體面而來)和你性格與文化是否相符。全部答案都應該圍繞這兩點組織(即每一個經歷都應迴歸到你經過這個經歷學到什麼,該職位所需關鍵技巧,這些經歷爲什麼讓你想作這個工做,和該經歷體現出你什麼樣的我的風格)。對這個問題由於好的回答而留下好印象很難,
  
  關鍵是避免留下壞印象。
  
  要點如下:
  
  1)避免拈輕怕重,不要談一個算不得缺點的缺點。好比熬夜會困,或者(待人接物)太客氣等等。
  
  2)避免談非職業缺點,好比有感情潔癖,挑食,不擅長陪女朋友逛街,作飯常常不懂會煮糊。
  
  3)避免談到沒法改善的弱點,好比我算數必須用計算器,我腦子很差用看書不理解。
  
  4)避免談到致命弱點,好比脾氣怪異,不喜歡合做,遲到早退等。
  
  那談什麼最好呢?我認爲要點有三:
  
  1)談已經在改正的缺點/有明確計劃來改正的缺點。尤爲是你可以充分論證在近期就能夠解決的缺點。
  
  2)談一個利用你的優勢改正的缺點,順便帶出一個優勢。(這是較高效的溝通技巧)
  
  相對較好的回答:
  
  1)喜歡追求細節致使項目/做業未能定期完成。經過時間管理能力改變工做方式,先完成框架再改善細節得以解決;
  
  2)不知如何拒絕,同事要求幫忙一律攬下,影響自身工做進度。經過多任務處理能力設定優先順序,以該優先順序表向求助同事展現本身手上工做,並給其一個本身在什麼時候能夠給予幫助的時間估計,讓求助人自行決定是否求助,問題解決
  
  3)對處理同一問題的解決辦法上,因爲組員本身的技術偏好和技術構成不同容易形成溝通障礙及影響項目計劃,因此,應學會高效和有效溝通方式及工做技巧
  
  閱讀更多
  
  資本寒冬下的android面經
  
  Android自定義View——啥是佩奇?
  
  輕鬆實現RecyclerView懸浮條,就是如此簡單!
  
  APK 的前世此生:從 Android 源碼到 apk 的編譯打包流程數據庫

相關文章
相關標籤/搜索