Android 開發中,有哪些坑需要注意?
樓主自己來一個,用appcompat21版的ActionBar高度默認是56Dp,不知道這個算不算
1、不要排斥新技術和新工具。
Android Studio 1.0 之後的版本,基本已經穩定到可以支持正常的工作開發的程度了。單純就書寫效率而言,Android Studio 帶來的好處絕對大於它和Gradle的學習成本。JetBrains的IDE,用過都說好。還有就是適當的提升targetSdkVersion到新版本。2、代碼設計方面的問題,大部分都能在Android系統源碼里找到解決方案。
當你想設計一個新模塊,或者實現一個新ui組件的時候,應該採用哪些設計模式、應該以哪種形式給外界提供介面之類的問題,大部分都可以參考Android系統的源碼,找到實現方式。Google為安卓程序員提供了一座現成的寶庫。
3、理解Android和Java內存管理方式,至少要理解垃圾回收和Java的引用。
就好比學OC就要先理解黃金法則一樣,而java的內存管理,其實比OC要好理解多了。 這可能會幫助你大大減少程序非同步操作產生的空指針崩潰。也會幫助你理解為什麼濫用單例模式會導致內存的臃腫。還會幫助你養成不用「+」去連接超大字元串的好習慣。4、ContentProvider並不是只有在跨進程共享數據的才有用,把資料庫表映射到一個獨立的uri是Google鼓勵的實現方式。
從設計上講,用uri(統一資源標識符)去描述數據,肯定比sql語句要理想。從效果上講,用CursorLoader讀取數據是讓iOS程序員都羨慕不已的事情,作為android程序員,何苦不用呢。5、理解Activity任務棧。
非Activity的Context對象如果直接啟動Activity會報錯,這只是一個表面現象,真正起作用的其實是Activity任務棧機制。理解Activity任務棧機制以及Activity的各種啟動方式,會幫助解決大部分頁面關係錯亂問題,以及應用互相掉起、任務欄進入應用、後台彈窗引起的各種問題。6、對於一些奇葩的第三方ROM,調用其非主流api的時候,可以使用反射。
在適配一些第三方ROM的的時候,調用一些在開發環境中沒有,但在運行環境中有的方法時,可以使用反射。比方說,華為雙卡手機可能會提供獲取第二塊SIM卡信息的api,如果直接調用,在開發環境可能無法通過正常編譯,用反射就沒問題。這屬於不得已而用反射的一種情況。7、SQLite的鎖,是資料庫級別的鎖,也就是說同一個資料庫的寫操作無法並發執行。
所以,在資料庫設計的時候,如果表太多,盡量將沒有關聯的表拆到多個資料庫文件中。8、Bitmap的內存佔用問題。這是一個困擾2.X時代android程序員的問題。2.X時代Bitmap對象雖然存儲在堆內存中,但是用了一個byte數組存儲其像素信息。通過計數器來記錄該像素信息被引用的個數。有人認為這個byte數組在native堆中,但事實上它也在堆中。只有在使用者調用recycle()後,Bitmap對象才會釋放像素信息,才會在失去引用後,被垃圾回收機制銷毀。再加上DVM的heap size有嚴格的閥值,所以在使用大量圖片資源的時候,及其容易發生OOM。解決辦法一般都是,用一個哈希表存儲Bitmap對象的軟引用,作為內存緩存,並在適當時機掉用其recycle()。3.0以上版本Bitmap對象可以通過垃圾回收機制完全銷毀,理論上不用再調用recycle()。作為一個有三、四年Android應用開發經驗的碼農,自然會遇到很多坑,下面是我能夠想起的一些坑(實踐證明不記筆記可不是個好習慣),後面有想到其它坑會陸續補上。
- 在Android library中不能使用switch-case語句訪問資源ID:在Android library中不能使用switch-case語句訪問資源ID的原因分析及解決方案
- 不能在Activity沒有完全顯示時顯示PopupWindow和Dialog:popupwindow - Problems creating a Popup Window in Android Activity
- 在多進程之間不要用SharedPreferences共享數據,雖然可以(MODE_MULTI_PROCESS),但極不穩定:android - MODE_MULTI_PROCESS for SharedPreferences isn"t working
- 有些時候不能使用Application的Context,不然會報錯(比如啟動Activity,顯示Dialog等):
1、數字1:啟動Activity在這些類中是可以的,但是需要創建一個新的task,一般情況不推薦;
2、數字2:在這些類中去layout inflate是合法的,但是會使用系統默認的主題樣式,如果你自定義了某些樣式可能不會被使用;
3、數字3:在Receiver為null時允許,在4.2或以上的版本中,用於獲取黏性廣播的當前值。(可以無視);
4、ContentProvider、BroadcastReceiver之所以在上述表格中,是因為在其內部方法中都有一個context用於使用。
- 同一個應用的JNI代碼,不要輕易換NDK編譯的版本,否則會有很多問題(主要是一些方法實現不一樣,並且高版本對代碼的檢測更嚴格),比如r8沒有問題,但到r9就有問題了,這是個大坑;
- Android的JNI代碼中,有返回類型的函數沒有返回值編譯的時候也不會報錯;
- 當前Activity的onPause方法執行結束後才會執行下一個Activity的onCreate方法,所以在onPause方法中不適合做耗時較長的工作,這會影響到頁面之間的跳轉效率;
- 謹慎使用Android的透明主題,透明主題會導致很多問題,比如:如果新的Activity採用了透明主題,那麼當前Activity的onStop方法不會被調用;在設置為透明主題的Activity界面按Home鍵時,可能會導致刷屏不幹凈的問題;進入主題為透明主題的界面會有明顯的延時感;
- 不要在非UI線程中初始化ViewStub,否則會返回null;
- 公共介面一定要考慮到代碼重入的情況,能設計為單例就盡量用單例;
- 不要通過Bundle傳遞大塊的數據,否則會報TransactionTooLargeException異常:java - Issue: Passing large data to second Activity
- 盡量不要通過Application緩存數據,這不穩定:不要在Android的Application對象中緩存數據!
- (AnimationDrawable在Android5.0及以上的版本已有明顯的優化)盡量不要使用AnimationDrawable,它在初始化的時候就將所有圖片載入到內存中,特別占內存,並且還不能釋放,釋放之後下次進入再次載入時會報錯;
- 9圖不能通過tinypng壓縮,不然會有問題;
- genymotion模擬器快是因為它是基於x86架構的,如果你的應用中用到了so,但沒有x86架構的so,只能放棄使用它;Android Studio的模擬器也一樣;
- Eclipse的Android開發環境配置好後不要輕易升級ADT和build tools,不然會浪費你很多時間,還有就是一個workspace中的工程不要太多,不然每次啟動都會很慢;
- Android studio每個版本、gradle每個版本差別都比較大(我是這樣認為的),對於jni代碼的編譯建議在Eclipse中進行,如果在Android studio中開發jni會浪費很多時間,主要是編譯腳本的配置比較麻煩;
- Eclipse中的Lint太不靠譜,特別是主工程中依賴library的時候,很多提示都是有問題的,建議使用Android Studio的工程清理工具,特別推薦;
- 不同API版本的AsyncTask實現不一樣,有的是可以同時執行多個任務,有的API中只能同時執行一個線程,所以在程序中同時執行多個AsyncTask時有可能遇到一個AsyncTask的excute方法後很久都沒有執行。調用AsyncTask的excute方法不能立即執行程序的原因分析及改善方案
- 同一個應用,相同的圖片分別放在drawable-xxhdpi、drawable-xhdpi、drawable-hdpi、drawable-mdpi、drawable-ldpi中,在同一設備中佔用的內存會大不一樣(設備的dpi是固定的,圖片放在不同的dpi文件夾下,在設備上顯示時需要將圖片轉換成和當前屏幕一樣dpi後在設備中顯示,所以即使該圖片在不同dpi文件夾下大小一樣,但放在內存中的大小卻不是一樣的,並不一定是長*寬*4),做應用的內存優化之前可以先看一看你的工程是如何做屏幕適配的,是否有優化的空間。強烈推薦這個屏幕適配視頻教程,花兩個半小時就能看完:Android-屏幕適配全攻略
- 謹慎對待資料庫升級(比如需要在原資料庫中增加欄位),避免數據丟失或者操作資料庫異常的情況,資料庫升級方法可以查閱《第一行代碼》P263;
- 多個程序共用一套代碼(一套代碼,在桌面上多個圖標)時需要處理好不同入口進入時的堆棧問題;
- 使用Adapter的時候,如果你使用了ViewHolder做緩存,在getView的方法中無論這項的每個視圖是否需要設置屬性(比如TextView設置的屬性可能為null,item的某一個按鈕的背景為透明、某一項的顏色為透明等),都需要為每一項的所有視圖設置屬性(textview的屬性為空也需要設置setText(""),背景透明也需要設置),否則在滑動的過程中會出現內容的顯示錯亂。
- 謹慎使用Android的多進程,多進程雖然能夠降低主進程的內存壓力,但會遇到如下問題:(1)不能實現完全退出所有Activity的功能(如果有同行在應用內採用多進程成功實現過完全退出程序歡迎溝通交流);(2)首次進入新啟動進程的頁面時會有延時的現象(有可能黑屏、白屏幾秒,是白屏還是黑屏和新Activity的主題有關);(3)應用內多進程時,新啟動一個進程都會重新跑一次Application的onCreate方法,不上重新創建一個Application,但會重新跑Application的onCreate,這樣就不能在Application中緩存數據作為內存共享的途徑了;(4)多進程間通過SharedPreferences共享數據時不穩定,具體可以查閱《Android開發藝術探索》。
- 使用Toast時,建議定義一個全局的Toast對象,這樣可以避免連續顯示Toast時不能取消上一次Toast消息的情況(如果你有連續彈出Toast的情況,避免使用Toast.makeText);
- View的面積越大繪製的時間就越長,透明通道對View的繪製速度影響很大;
- 不要通過Msg傳遞大的對象,會導致內存問題。
- 關於AS的使用經驗,參見:[Android Studio使用過程中需要弄明白的一些問題](Eclipse轉Android Studio的過程中有必要弄明白的一些問題 - 張明雲的知識共享 - 知乎專欄)
- Eclipse的工程轉成AS的版本後,在同一個機器中安裝會報」INSTALL_FAILED_VERSION_DOWNGRADE「這個錯誤,原因是因為as除了可以在Manifest.xml文件中設置apk的版本名和版本號,還可以在build.gradle文件中設置apk的版本名和版本號,記得修改build.gralde中的版本名和版本號到最新就可以了;
- 通常情況下,在插入USB之後可能會跳轉到一個新的界面,這時候可能你本來是橫屏的,突然跳轉到這個新界面是豎屏的,雖然你的界面被壓在下面,但是還是會被強制橫豎屏切換一次,如果這時候你的界面不做處理就會重載,如果你的界面裡面有很多fragment,這時候的重載更加複雜,難以處理。所以建議不做橫豎屏切換的界面都弄一下橫豎屏切換不重載。
- 如果你在 manifest 中把一個 activity 設置成 android:windowSoftInputMode="adjustResize",那麼 ScrollView(或者其它可伸縮的 ViewGroups)會縮小,從而為軟鍵盤騰出空間。但是,如果你在 activity 的主題中設置了 android:windowFullscreen="true",那麼 ScrollView 不會縮小。這是因為該屬性強制 ScrollView 全屏顯示。然而在主題中設置 android:fitsSystemWindows="false" 也會導致 adjustResize 不起作用;
- 做自定義手寫功能時,底層上報的點並不會都在MotionEvent中能夠及時接收到,比如底層一秒鐘200個點,上層收到的可能只有幾十個點,為了提高手寫的流暢度,在onTouchEvent中,通過MotionEvent中的getHistorySize能夠獲取到從底層傳輸到上層過程中所有的點;
- 在Android 4.0以後,在Manifest.xml中靜態註冊的廣播,程序安裝後必須啟動一次才能接收到廣播,比如你的應用監聽開機啟動的廣播,必須要你的程序被運行過才能監聽到;
- 一個AS的工程中,module不宜太多,否則會影響編譯的速度,建議將不是經常變動的module打包成aar,主工程直接依賴aar可以大大提高編譯的速度;
- 在AS中,如果你想動態同步一個依賴包的更新,可以在依賴包的最後面寫上「+」,比如:
compile "com.android.support:appcompat-v7:23.0.+"
,但這種方法需要謹慎使用,否則會因為依賴包的變動導致你的項目不穩定:Don"t use dynamic versions for your dependencies
- release版本的apk需要簽名才能正常安裝;
- 在2.3之前GC操作是不能並發進行的,也就是系統正在進行GC程序就只能阻塞住等待GC結束,在2.3之後GC操作改成了並發的方式進行,GC過程中不會影響程序的正常運行,但在GC操作的開始和結束還是會短暫阻塞一段時間。所以頻繁的GC會導致使用應用的過程中卡頓,所以為了應用在使用過程中更流暢,需要盡量減少觸發GC操作,這涉及到性能優化,對於靜態代碼的分析,AS已經很強大了,可以使用Android Studio的Analyze→Inspect Code...進行分析;
- 盡量避免給window和Activity同時都設置了背景,這樣會造成過渡繪製,可以通過在給Activity設置主題時,去掉windowBackground背景的方式減少一層過渡繪製,有時候為了避免進入Activity時會黑屏或者白屏(和主題有關),會在給Activity設置主題的時候給window設置背景,如果這種情況下給Activity也設置了背景,是會增加一倍內存的:
&
- 一個類的finalize方法調用時機是不確定的,應該避免指望通過這個方法去釋放與類相關的資源,否則會導致一些隨機bug;
- Activity的onDestory方法調用時機是不確定的(有時候離開界面很久之後才會調用onDestory方法),應該避免指望通過onDestory方法去釋放與Activity相關的資源,否則會導致一些隨機bug;
- 不要指望MAT明確告訴你哪裡存在內存泄露,它只會提供各個類間的引用關係,所以可以通過leakcanary或者通過adb shell dumpsys meminfo packagename查看進入/退出一個界面後activity和views數量的變化情況,來初步定位可能存在內存泄露的地方,然後通過MAT工具找到具體的地方。
Android 6.0 中,使用 SYSTEM_ALERT_WINDOW 繪製的懸浮窗不能含有 elevation 屬性,否則會在真機上崩潰,模擬器正常。使用 AppCompat v21+ 後,在 LG 4.1- 帶有實體菜單鍵的機型上按菜單鍵會崩潰。三星 5.0-5.1 機型上 DatePicker 控制項會崩潰。MIUI 上 SYSTEM_ALERT_WINDOW 需要額外申請許可權,默認會拒絕掉,除非 type 設置為 TYPE_TOAST。其他很多忘了,想到再補充。另外 bugme 上面一切看起來好像正常的代碼都有可能蹦。
謝邀 @張明雲
這個問題很早就關注了, @張明雲 與不少同學的回答都很贊,我個人平時也沒有填完坑隨手記錄的習慣,踩過的坑再一一撿起來比較費勁了,不過還是可以提一點,貌似沒看到其它答主提到:
其實Android已經提供了一個平台,記錄了一些坑。
https://code.google.com/p/android/issues/list這其實是用來記錄Android系統的各種坑,等待Android官方修復的,但很多Android應用開發者們也會把開發過程中踩到的一些坑提交上去,而且Android系統的坑經常也是導致各種開發問題的根源,值得大家看看。比如最近有朋友遇到一個坑,明明沒有主動加READ_PHONE_STATE許可權,但卻被自動加上了這許可權,這個坑很早前坑過我們一次,還導致過Hotfix,我印象很深,就翻了出來,就是在這個網站找到的答案,各位有興趣的可以看看。https://code.google.com/p/android/issues/detail?id=81287
目前總共有46505個issue,Android的坑之多確實名不虛傳,當然這其中不排除有重複或無效的信息。
這麼多的issue怎麼看呢?很簡單,根據Star排個名,有興趣的可以挨個看看。
看看哪些坑最多人感同身受,掉進去的人最多,當然還有諸如Status, Priority以及各種高級Search技巧,可以方便查看你自己感興趣領域的坑。我們也是經常在踩到坑之後,各種Google最後被引導到這個網站,找到了答案,相信不少同學也有這方面的經歷,當然都是英文內容,也許還要翻牆,但這對我們有志搞好Android開發的同學來說,不應該是問題。最近遇到的一個,特來補充:
Android 的 PackageManager 在 App 升級時 .so 庫可能沒有成功複製到 /data/data/xxx/lib/ 下,所以在載入 .so 庫時會出現 java.lang.UnsatisfiedLinkError 錯誤。
解決辦法:如果找不到.so文件,就從apk中解壓相應的 .so 文件複製到指定目錄下。
由於我們的產品用了 fresco ,很大一部分 Crash 是 fresco 的 SoLoaderShim.java 這個類造成的,而這個類簡單地使用 System.loadLibrary 來載入 .so 庫。
已經有庫子來解決這個問題了:GitHub - KeepSafe/ReLinker: A robust native library loader for Android. 。
不過ReLinker並不能處理 .so 依賴 .so 的情況,Facebook 最近出了一個 SoLoader:GitHub - facebook/SoLoader: Native code loader for Android ,它可以自動解決依賴的問題。另外,fresco 的 issue 里看到回復說,之後的更新會用上 SoLoader。說幾個之前遇到過的坑(大神們輕笑):1、假使AActivity已經啟動(對應的啟動Intent為intent1),此時調用startActivity(intent2)再次啟動AActivity,在onResume()中調用getIntent()獲取到的Intent仍然是intent1,除非重寫onNewIntent()方法:
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
view.setTag(DEFAULT_TAG + position);
container.addView(view);
return view;
}
View child = mViewPager.findViewWithTag(DEFAULT_TAG + position));
來獲取。
3、自定義View為內部類時,如果需要在xml文件中使用,該View必須為靜態內部類,當然這不是重點,重點是xml中必須使用view作為節點:&
&
&
&
&
&
5、HONEYCOMB以上使用混合渲染器ComposeShader無效,可能和硬體加速有關,詳見:
canvas - Issue with ComposeShader on Android 4.1.1使用drawable設置的虛線效果無效也可能是硬體加速的原因。6、使用hide()與show()來切換Fragment時,Fragment的生命周期方法都不會被調用,除了onHiddenChanged()。
7、自定義SeekBar thumb的問題,代碼如下:android:thumb="@drawable/sb_thumb"
&
&
&
&
&
&
&
但是效果是這樣的:
需要計算thumbOffset大小並設置才能正常顯示。8、CheckBox設置文本時的顯示問題,我就傳幾張圖不說話,呵呵……
參見:Android - Spacing between CheckBox and text9、使用MediaPlayer播放網路視頻時,如果網路不好會一直載入,點擊返回可能ANR、鎖屏可能ANR、隨意拖動進度條也可能ANR,不得不說Android媒體這一塊做的實在不夠好。
10、默認一個應用對應一個進程,在AndroidManifest.xml文件中給組件添加android:process屬性後(比如友盟推送:android:process=":push"),應用會對應多個進程,Application會被創建多次,此時內存中的數據都不能共享(即便是靜態的成員)。
11、Fragment千萬不能設置成非靜態內部類,因為Activity恢復狀態時會通過反射的方法實例化Fragment。詳見:Android Fragment$InstantiationException為了追求各種效果,用了無數個第三方庫並且上線之後,發現六萬五千個函數的限制的存在
小米的手機Toast任意布局都不會出問題,其他手機崩潰。不小心改動了一個控制項的id,造成了一個控制項的空引用,並且只是setText一個常量字元串,在小米手機上不會崩潰,其他手機死一片。在小米手機上使用SurfaceView時,並沒有在創建完成的回調裡面進行操作,直接在構造裡面進行一些操作,完美通過,其他手機崩潰一片。跪求小米ROM團隊不要在FrameWork層打這麼多補丁...
三星
剛剛遇到一個:(gradle plugin 1.3.0,gradle 2.4.0)1.app的build.gradle中productFlavors 隨手添加了一個main,代表「野路子」安裝的,誰知道死活編譯通不過,猜測可能main是保留字。「main { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "Main"] }」這貨
productFlavors {
main {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "Main"]
}
xiaomi {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "Xiaomi"]
}
_360 {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "_360"]
}
baidu {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "Baidu"]
}
wandoujia {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "Wandoujia"]
}
}
This has to be a bug in appcompat. I had a similar problem with abc_screen_simple.xml
shrink resources was working for about a month before the lollipop release broke it.
1、改變TextView中部分文字的顏色2、隱式的啟動一個Activity
imageview和textview永遠都對不齊,算是一個坑嗎
多買一些國產ROM 的機型來測試。
說下這段時間遇到的問題1.要實現popupwindow點擊外部dismiss的話,要在代碼中設置其background2.在android studio中使用android:icon=icon格式的圖片來設置app圖標,會使as的xml設計界面崩潰,要用android:logo=icon格式,或者android:icon=png格式,是不是很坑爹?3.父控制項高和寬設為wrap_content的話,子控制項alignparent後怎麼margin也沒有用。
魅族,小米和三星,沒事瞎改球!
一、Android6.0 「第三種」許可權問題:
android.permission.WRITE_SETTINGS不能自動授權,也不能運行時請求授權,咋整啊?通過打開Intent來讓用戶手動設置。貌似SETTINGS的許可權只能這麼處理,from CommonsWare research Android 6.0 changes.
二、三星 Galaxy S4 BluetoothGatt: Failed to register callback,需要UI線程調用:(device#connectGatt, connect, disconnect, etc)
三、其它可以這裡看看這裡:http://askandroid.sinaapp.com/
ps:其實大多數解決方案都來源於:http://stackoverflow.com對於API 如果要用gson之類的把resp mapping到model的話 建議儘早引入Optional (或者直接Kotlin)做好每個變數的null check 能減少80%和後端撕逼丟鍋的問題
先來一篇Android Studio使用指南,裡面包含一些報錯的解決方法。
Android Studio使用指南再來一篇寫代碼時候的一些套路,幫助你寫代碼更優雅,更好維護(仍然再整理新的套路,應該會有續篇)Android開發套路收集整理與討論我覺得android開發中最大的坑,是讓幾年前還很菜的我誤以為,不就是寫java嗎,這個我會啊
於是很happy的寫了幾年app....最近兩年,啃了三本老外寫的andoid書之後,開始接觸c/c++, Linux的東西。再也不覺得它跟Java有那麼強關係。看到好多人在share,本寶寶也share自己的吧,雖然入行還不久,但是本寶寶勤(sha)奮(bi)遇到了很多的bug記錄了下來,用的是印象筆記。1,最常用的,更新SDK有效地址和配置http://mirrors.neusoft.edu.cn 和截圖2,對於ViewGroup組件,xml設置android:descendantFocusability屬性,控制是否讓子控制項先獲得焦點,有
beforeDescendants:viewgroup會優先其子類控制項而獲取到焦點
afterDescendants:viewgroup只有當其子類控制項不需要獲取焦點時才獲取焦點
blocksDescendants:viewgroup會覆蓋子類控制項而直接獲得焦點3,使用自己下載的JAR包的時候,他的位置是lib目錄下面,假如不存在,那麼就新建lib目錄,與src和build同一個等級。4,在onTouchEvent當中,使用getX和getRawX的區別其中getX是相對於容器的坐標,比如他是在某個ListView中,或者其他ViewGroup當中。getRawX是相當於他在屏幕的坐標。5,ExpandableListView設置不可收縮,改事件返回true即可,對於點擊childListView沒有影響。 listView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
return true;
}
});
6,Android StudioR文件的位置:
在Project視圖下面,對應的model名字/build/generated/sorce/r/debug-項目名稱-R7,Android Studio配置Lambda表達式:在Project的build.gradle中的節點dependencies中添加classpath "me.tatarka:gradle-retrolambda:3.2.0"
apply plugin : "me.tatarka.retrolambda"
compileOptions {
sourceCompatibility JavaVersion. VERSION_1_8
targetCompatibility JavaVersion. VERSION_1_8
}
//轉換dip為px
public static int convertDipOrPx(Context context, int dip) {
float scale = context.getResources().getDisplayMetrics().density;
return (int)(dip*scale + 0.5f*(dip&>=0?1:-1));
}
//轉換px為dip
public static int convertPxOrDip(Context context, int px) {
float scale = context.getResources().getDisplayMetrics().density;
return (int)(px/scale + 0.5f*(px&>=0?1:-1));
}
public static int sp2px(Context context, float spValue) {
float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
public static int px2sp(Context context, float pxValue) {
float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (pxValue / fontScale + 0.5f);
}
來自:TypedValue.applyDimension 中dp和sp之間轉化的真相
推薦閱讀:
※以手機操作系統為例,我們經常說系統或者某個軟體優化好不好,到底什麼是優化?
※金山手機毒霸屏蔽 App 內廣告的做法和 AdBlock 等服務的做法有何不同?是否應該譴責?
※Nvidia Maxwell用ARM替換掉command processor有什麼意義?
※知乎上有哪些 Android 開發的大牛?