本文是做者在Android開發實踐中的隨手速記,記錄一些小問題的解決方案和注意事項,持續更新。html
如下是速記內容,如有不嚴謹的地方,望小夥伴們指出。java
1.Module 不生成R文件,可嘗試取消對該Module的引用,
取消後AS會再次編譯工程,看看此時可否生成R。react
2.Activity theme設置錯誤時,會出現:
java.lang.ClassCastException: android.widget.LinearLayout$LayoutParams
cannot be cast to com.android.internal.widget.ActionBarOverlayLayout$LayoutParams
此時,須要爲Activity/Application指定帶ActionBar的系統樣式,或讓自定義的Theme集成自帶ActionBar
的系統樣式,固然也能夠改用普通Activity類,而非使用Actionbar的Activity子類。android
3.java.lang.IllegalArgumentException: NaN is not a valid double value as per JSON
specification. To override this behavior, use GsonBuilder.
serializeSpecialFloatingPointValues() method.
4.AndroidStudio中引用Module時,Module中同名的資源會被App中的資源替換,
利用這一點能夠實現自定義資源而不修改Module。目前只試過String.git
5.Dagger 環境配置(可解決不能生成Dagger類的狀況):http://www.itnose.net/detail/6353446.html
http://stackoverflow.com/questions/29562347/how-do-i-configure-intellij-gradle-to-use-dagger-2-0web
6.Android TouchDelegate 只能擴展同一個ViewGroup中的一個View的響應範圍。sql
7.Baidu Map V3.7 MKOfflineMap 下載完成後不可調用destroy方法(也許下載完成後百度在作一些善後事宜),
不然離線地圖可能沒法正常使用。另外此版本的MKOLUpdateElement.status永遠爲1,不可靠~shell
8.ART JNI、GC http://developer.android.com/guide/practices/verifying-apps-art.html數據庫
9.IDEA更新JDK至1.8(From1.7),編譯代碼時出現:
Error:(18, 6) java: -source 1.3 中不支持註釋
(請使用 -source 5 或更高版本以啓用註釋)
打開Project Structure,在Project欄中找到Project language level,修改爲1.3以上版本便可。
10.當爲Activity寫了Portrait和LandScape兩種佈局時,在佈局文件根節點上添加Tag值,在運行時讀取可區分Portrait和LandScape。編程
11.打開應用,使用adb shell dumpsys activity top,能夠查看應用Activity的信息,也能夠獲取包名。
12.啓動Activity的時候,設置Flag,Intent.setFlags(Intent.Flag_Activity_New_Task|Intent.Flag_Activity_Clear_Task)能夠清空BackStack。
13.Context.createPackageContext(pkgName,flags)能夠根據包名建立另外一個Application的context,前提是兩者的shareUserId和Signature要相同,這樣就
兩個應用就會運行在同一個Process中,主應用就能夠訪問附屬應用的Resources和Classloader(context.getClassloader.load(className)).安裝在設備中的每個apk程序,Android系統會給其
分配一個單獨的用戶空間,其中android:shareUserId就是對應一個Linux用戶ID,而且爲它建立一個沙箱,以防止與其它應用程序產生影響。用戶ID
在應用程序被安裝到設備中時分配。經過SharedUserid,擁有同一個Userid的多個APK能夠配置成運行在同一個進程中,因此默認就是能夠互相訪問任
意數據,也能夠配置成運行在不一樣的進程中, 同時能夠訪問其APK的數據目錄下的資源(圖片,數據庫和文件),就像訪問本程序的數據同樣。
14.Activity View 層級:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0331/1608.html
15.動態加載機制:http://blog.csdn.net/jiangwei0910410003/article/details/17679823
16.繼承的壞處:Super方法裏引用了可被子類複寫的方法時,該方法也會被子類改寫(調用Super.method也無效)。
17.Android 6.0 File.mkdirs()無效,是由於權限控制,可動態申請權限:http://stackoverflow.com/questions/32225506/android-6m-permission-issue-create-directory-not-working
18.爲一個Resources建立LayoutInflater用於inflate該Resource中的layout,須要Extend ContextThemeWrapper實現一個ResourcesContext,
而後使用 LayoutInflater.from(Context).cloneInContext(ResourceContext);
19.ListView Item中的可點擊控件
20.使用Navigator來導航能夠避免Activity相互引用,在Activity中寫獲取啓動它的Intent的方法能夠避免對外定義傳參Key。
21.使用android.R.id.content能夠獲取Activity的根元素。
22.Java包內外層須要互相引用,沒有內層能夠直接使用外層或者外層能夠直接使用內層之說。
23.在Java7以前,switch只能支持 byte、short、char、int或者其對應的封裝類以及Enum類型。在Java7中,支持了String。
24.解決動態加載SurfaceView閃屏問題的兩種方式:一,getWindow().setFormat(PixelFormat.TRANSLUCENT); 二,在佈局中添加一個
不可見的SurfaceView。
25.使用Fragment.onActivityCreated()來retrieve view和restore view state。
26.Android 經過Intent.setComponent(new ComponentName(PkgName,ClassName))能夠啓動另外一個Apk的Activity;經過new
DexClassLoader(String dexPath, String optimizedDirectory, String libraryPath, ClassLoader parent)可加載執行Jar/Apk中的代碼。
27.ScrollView中內容不足以填充到全屏時,須要添加android:fillViewport="true"來讓ScrollView填滿全屏。
28.Apk的Resource ID信息沒有放在classes.dex中,放在Resources.arsc中?? See:http://blog.csdn.net/luoshengyang/article/details/8744683
和http://blog.csdn.net/luoshengyang/article/details/8806798
29.Android浮點運算:嵌入式處理器一般沒有支持浮點運算,全部對"float"和"double"的運算都是經過軟件
實現的。一些基本的浮點運算,甚至須要毫秒級的時間才能完成。甚至是整數,一些芯片有對乘法的硬件支
持而缺乏對除法的支持。這種狀況下,整數的除法和取模運算也是由軟件來完成的。因此當你在使用哈希表
或者作大量數學運算時必定要當心謹慎。
30.Git 只clone一個分支:git clone -b <branch> <repo>
31.Java 1.5開始支持靜態引用,能夠直接引用靜態方法,省略調用靜態方法時須要寫類名的工做。使用 import static <class>.* 可引入全部靜態方法。
32.Android Activity中 getApplicationContext!=getBaseContext(),後者是爲每一個Activity從新建立的一個ContextImpl,Activity自己是一個
ContextThemeWrapper,它依靠ContextImpl來完成實際的工做。
33.Thread的looper和MainThread的MainLooper都是直接new出來的,本質上沒有區別,啓用了Looper的Thread建立的Handler能夠執行UI操做
,可是這裏的操做若是耗時過久的話(如sleep>100ms),容易崩潰(待驗證,當耗時操做在前易崩潰)。
34.ActivityManager.getRunningTasks(1).get(0).topActivity()可獲取前臺應用的Activity componentName。
35.若是使用Application的Context來bindService,Service就會跟Application的生命週期同樣,而不會受Activity的生命週期影響。若是是用某個
Activity的Context來綁定Service,這個Service的生命週期就受到這個Activity(而非App的其餘Activity)的生命週期影響,而且無需調用UnbindService。
36.Exception raised during rendering: com/android/util/PropertiesMap (Details),在渲染預覽界面更改渲染工具版本便可。
37.AndroidStudio Ignore Files:
.idea
.gradle
build/
local.properties
*.iml
38.Android 切圖中不規則的圖片(兩頭純圓按鈕)或純規則圖片(純圓,正方形?)沒法作.9拉伸,作成Bitmapdrawable(<bitamp/>)能夠解決。
39.Android添加懸浮窗顯示,須要使用Application的Context,如若不能顯示在全部應用上層,則需使用Service?
40.SurfaceView黑屏:(1)getWindow().setFormat(PixelFormat.TRANSLUCENT);
41.Gson序列化時排除字段:http://www.tuicool.com/articles/v2eIrqz
42.引入關聯表來關聯兩個表之間的關係。
43.Gson 轉換List<T>時,須要使用new TypeToken<List<String>>(){}.getType(),特別注意TypeToken後面的大括號。
44.以文件夾方式隔離用戶數據,將用戶數據(包括數據庫)都放到帶用戶信息的文件夾下面。
45.Android 沒法實現不影響後面操做的懸浮操做?
46.使用wait()和notify()時通常是爲了同步線程,可是要注意,若是所調用的方法沒有開啓異步線程,可能會直接返回,這時候在方法調用以後
使用的wait()就會一直等待異步回調來notify,然而回調其實早就已經在方法棧中發生,這樣就會致使線程一直等待。若是開啓了異步線程,那wait()必定會等到notify的到來。
47.Java 使用泛型時,支持自動以泛型的具體類型來命名參數,只要讓泛型對應的參數名與泛型名同樣(不區分大小寫)就能夠作到。
48.Sqlite 查詢爲空的字段 Field IS NULL, 查詢不爲空的字段 Field IS NOT NULL。
49.ImageView tint in xml and setColorFilter 能夠對圖片進行着色,可用於改變圖標的顏色,使用PorterDuff.Mode.CLEAR時,還能夠隱藏繪製內容。
50.FileOutputStream.getChannel().lock() 能夠得到一個FileLock以鎖定文件。
51.解決Gradle DSL method not found: ‘android()’:刪除Project的build.gradle文件中的:android{}便可。See:http://www.hloong.com/?p=100
52.ListView 的Item中有可點擊元素時,需將可點擊元素的Focusable和FocusableInTouchMode屬性設置爲false,併爲ListView設置android:descendantFocusability="blocksDescendants"
這樣按鈕和Item均可以點擊。
53.Root 原理:http://www.myhack58.com/Article/html/3/92/2013/36574.htm
54.requestWindowFeature()用來動態的決定Window的特性,而這個行爲發生在setContentView以前,因此必需要在setContentView以前設置。如request
WindowFeature(Window.FEATURE_NO_TITLE)以後,Window中的DecorView就不會生成TitleView部分,而只生成ContentView部分。
55.Android Style中使用自定義View屬性時,不用加任何命名空間(如android:xxx),直接使用屬性名便可
56.PopupWindow點擊外部消失,只需設置background便可: setBackgroundDrawable(new BitmapDrawable())
57.Sqlite不可在事務中開啓另外一個事務,不然這個事務操做無效。
58.new SimpleDateFormat("yyyy-M-d hh:mm").format(date)能夠去0。
59.View 在綁定後,從View樹中移除後再添加,綁定的數據依然有效。
60.EditText設置inputType="numberSigned"時能夠輸入負數。
61. <item name="android:imeOptions">flagNoExtractUi</item>可禁止輸入法開新界面全屏輸入
62.Sqlite 關聯查詢:SELECT A.*,B.name FROM Task AS A ,Project AS B WHERE A.Status<='2'
63.Adapter.getItemViewType()返回的Type範圍應該是(0,ItemViewTypeCount]
64.Fatal signal 11 (SIGSEGV), code 0, fault addr 0x61b6 in tid 25110 (RenderThread) 跟硬件加速有關,避免設置
View.setLayerType(View.LAYER_TYPE_HARDWARE, null),出現問題時可在Manifest中禁用硬件加速:<android:hardwareAccelerated="false">
65.NDK_PROJECT_PATH=null,在app/build.gradle的android{}中添加
sourceSets.main {
jni.srcDirs = []
jniLibs.srcDir 'src/main/libs'
}
便可解決。
66.計算大數值時容易溢出,最好轉換爲大數值類型計算:如long EXPIRE_LOGIN =90* 24 * 60 * 60 * 1000 結果爲負數,應改成:
long EXPIRE_LOGIN =90L* 24 * 60 * 60 * 1000;
67.fitsSystemWindows實現沉浸式:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/1122/3712.html
68.app:layout_behavior="@string/bottom_sheet_behavior"
69.Application 中的OnTrimMemory用於系統恢復內存,此時可將一些不重要的內存緩存釋放掉。
70.ImageView adjust to Image,user adjustViewBounds=true and maxWidth/maxHeight of ImageView.
71.<item name="android:windowDrawsSystemBarBackgrounds">false</item> 控制內容是否渲染到底部欄下面
72.Sqlite DISK IOERROR WRITE,是由於臨時目錄問題,能夠經過設置之解決問題:
http://blog.csdn.net/u011453773/article/details/50731331
73.Android 調用系統分享:http://stackoverflow.com/questions/30518321/on-android-m-how-to-configure-the-direct-share-capabilities-image-text-an/30721038#30721038
74.獲取Android 的ContentView的容器能夠經過它的ID: Window.ID_ANDROID_CONTENT。
75.Java中Object的hashcode返回一個int的hash值。默認狀況下,Object中
的hashCode() 返回對象的32位jvm內存地址。也就是說若是對象不重寫該方
法,則返回相應對象的32爲JVM內存地址。equals方法返回true的兩個Objec
t應該返回相同的hashcode。因此通常Object的子類在是想equals方法和hashcode
方法的時候,要麼同時實現,要麼都不實現。這對於鍵值對使用時應該很關
鍵。重寫equals和hashcode時,可使用IDE提供的方法,安全高效。參考:
https://www.oschina.net/question/82993_75533 同時注意ORM的狀況。
76.Collections.synchronizedXXX(),是對全部的傳入對象加了同步鎖。
77.HashMap 操做都是經過數組找鏈表頭結點,key用於hash後找到數組index。
它的containskey也會經過key的hash找到對應鏈表頭結點,而後遍歷,可是containsValue由於不知道
key,沒法hash找到index,因此是按數組順序依次遍歷每個鏈表查找,效率較低。
78.AndroidStudio 編譯報錯: Error:java.lang.NullPointerException
(no error message),刪除工程目錄下.gradle文件,重啓就好。
79.GreenDao侷限性:不能兼容模型的繼承關係,沒法將父類的字段生成數據庫字段,若是父類和子類都有
都建了表,Dao之間沒有繼承關係。此時可能考慮合併連個表。
80.serialVersionUID 的意義:http://lenjey.iteye.com/blog/513736
81.ScrollView 嵌套GridView或者ListView,能夠重寫onMeasure方法,設置
測量高度爲最大值,測量模式爲AT_MOST,實現跟隨ScrollView滾動。此時若是
遇到佈局自動滾動到GridView所在位置,禁用GridView focus便可。
82.HttpUrlConnection 出現EOFException,聽說是當響應的InputStream 是 GZIPInputStream時,會形成 HTTP HEAD 的衝突,此處應該是個Bug,緣由能夠參考如下網址:
https://code.google.com/p/android/issues/detail?id=24672 , 能夠經過設置 connection.setRequestProperty( "Accept-Encoding", "" )解決.
83.RecyclerView的Item佈局中不能直接使用View,需使用具體的View。不然可能會報CreateViewFromTag Nullpointer。
84.在返回集合的方法中,不建議返回null,而是返回Collections.emptyxxx。
85.List泛型參數的子類和父類的轉化,能夠先將待轉換的類轉換爲泛型集合,而後賦值給接收者,如A和B ,
其中 B extends A,須要list<B> 轉換爲list<A>時 , 能夠這樣:
List list=list<b>;
List<A> receiver=list;
也能夠直接
用List.class.cast()方法,如:
List<A> receiver=List.class.cast(list<B>);
86.Seekbar滑塊偏上時,同時加上maxHeight和minHeight能夠解決,他們是用來指定進度背景高度的。
87.AdapterView中View的狀態不變化時(應用selector),和處理點擊控件同樣處理便可,關閉focusablity,加上FocusblockDesendants.
88.PNG使用Bitmap.compress壓縮質量時會忽略quality,建議使用webp。
89.四種方式設置Activity跳轉動畫:http://blog.csdn.net/qq_23547831/article/details/51821159
90.XListView 須要設置Adapter才能顯示Header,Footer和上下拉動
91. Dex cannot parse version 52 byte code,須要在App gradle 的android{...}中添加:
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
若是有Jack錯誤,還須要在defaultConfig{...}中添加 jackOptions { enabled true }
92.Collections.synchronizedList中全部方法都加了synchronize(mutex){...}同步,除了訪問iterater的方法,須要手動加鎖,請看他們的實現以下:
public ListIterator<E> listIterator() { return list.listIterator(); // Must be manually synched by user } public ListIterator<E> listIterator(int index) { return list.listIterator(index); // Must be manually synched by user }
93.用Gradle爲UMeng渠道打包首先你必須在AndroidManifest.xml中的meta-data修改如下的樣子:
<meta-data android:name="UMENG_CHANNEL" android:value="${UMENG_CHANNEL_VALUE}" />
而後再App的build.gradle的android{}中添加productFlavors {
YingYongBao {} HuaWei{} productFlavors.all { flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name] } }
注意其中渠道名不能以數字開頭。也可使用第三方PackNG打包,不過它的渠道沒有寫到Manifest中,若是二次簽名會致使丟失。
也能夠參考其餘不錯的多渠道打包工具,如騰訊企鵝電競開源的Vasdolly,美團的Walle。
94.Gradle讀取local.properties文件,以下讀取簽名配置信息
Properties properties = new Properties() InputStream inputStream = project.rootProject.file('local.properties').newDataInputStream() ; properties.load( inputStream ) //讀取文件 def sdkDir = properties.getProperty('key.file') storeFile file( sdkDir ) //讀取字段 def key_keyAlias = properties.getProperty( 'keyAlias' ) def key_keyPassword = properties.getProperty( 'keyPassword' ) ; def key_storePassword = properties.getProperty( 'storePassword' ) ; storePassword key_storePassword keyAlias key_keyAlias keyPassword key_keyPassword
95.LinearLayout比例佈局時,不包含0的weight時,使用0dp纔會準確。
96.出現 Bitmap too large to be uploaded into a texture錯誤時,是由於啓用硬件加速後,沒法顯示較大的圖片,解決方案三種:
(1)Android:hardwareAccelerated="false"關閉加速
(2)加載圖片時進行壓縮
(3)把大圖分割成小塊加載顯示圖片切片
97.Java 修改常量值,對於基本類型的常量會失效,由於Java編譯優化,對於基本類型的靜態常量,JAVA在編譯的時候就會把代碼中對此常量中引用的地方替換成相應常量值。
98.Android 錄屏命令:adb shell screenrecord /sdcard/demo.mp4
99.synchronized不能用在接口方法和抽象方法的聲明上,可是能夠用在實現上。
100.Realm跨平臺的高效數據庫方案。
101.CAS(Compare And Swap):一種在多線程環境中實現同步的CPU原子指令。它在向內存區域寫入值時,會先比較該內存區域現有值,若是值和原先讀到的值不一樣,
則寫入失敗。這是經過一個原子操做來完成的。原子性保證了值的時效性(最新)。 若是這個值已經被另外一個線程更新,那麼寫入將會失敗。這個操做必須代表值替換
是否成功:要麼用一個Bool表示,要麼返回內存區域現有值(有點兒像樂觀鎖)
102.子線程也能夠更新UI:http://www.cnblogs.com/lao-liang/p/5108745.html
103.git初始化沒有branch時,能夠先建立一個文件並commit,而後就會在本地生成master分支,此時push上去就行了。
104.Android style中設置版本兼容的屬性時,須要去掉android:前綴,不然可能無效。
105.Java中遍歷訪問,for是最快的,其次是foreach,再次是Iterator。有趣的是,使用Iterator時,編譯後的class是for循環,例如:
for(Iterator iterator = collection.iterator(); iterator.hasNext(); iterator.remove()) { ... }
106.將WebView嵌套在LinearLayout中使用,有可能加載不了使用Angular或者Vue寫的頁面,最好使用RelativeLayout做爲容器.
107.Android M及以上版本,可使用Settings.canDrawOverlay()判斷是否有懸浮窗權限:
private void checkOverlayPermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (!Settings.canDrawOverlays(this)) { Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())); startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE); } } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == OVERLAY_PERMISSION_REQ_CODE) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (!Settings.canDrawOverlays(this)) { // SYSTEM_ALERT_WINDOW permission not granted... } } } }
108.編譯時出現 ...NDK integration is deprecated in the current plugin. Consider trying the new experimental plugin...等NDK過期等錯誤時,需在
gradle.properties中添加
android.useDeprecatedNdk=true
109.應用在64位手機上加載.so報缺乏庫錯誤或者....so is 32-bit instead of 64-bit時(在已有Android項目集成react native也會出現該異常),是由於項目中64位庫不完整,此時須要排除64位庫,讓應用所有加載32位庫便可。過濾庫
須要在app/build.gradle中添加:
ndk { // 此處添加要保留的ABI abiFilters "armeabi-v7a", "x86", 'armeabi' } packagingOptions { // 此處排除掉64的庫 exclude "lib/arm64-v8a/libxxx.so" }
110.TextView 粗體切換:
//android中爲textview動態設置字體爲粗體 TextView textView = (TextView)findViewById(R.id.textView); textView .setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); //設置不爲加粗 textView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));
111.Gradle全局統一管理依賴,在項目根目錄建立config.gradle文件,在ext中定義依賴和版本:
ext{ android=[ ... compileSdkVersion:23 ... ] dependencies=[ ... "support-v4":'com.android.support:support-v4:23.1.1' ... ] }
而後在項目的build.gradle中添加apply from :「config.gradle」,在app的build.gradle中便可引用配置:
... compileSdkVersion rootProject.ext.android.compileSdkVersion compile rootProject.ext.dependencies["support-v4"] ...
也能夠在app的build.gradle中經過ext定義相關配置,而後引用,至關方便。
112.IDA Pro 可將.so反編譯爲彙編,若是配上F5插件,選中方法後按F5能夠查看對應方法的C/C++源碼。
113.AndroidStudio3.0如下(Gradle3.0如下)中作JNI開發,gradle.properties中添加android.useDeprecatedNdk=true,不須要寫MakeFile,而是直接在build.gradle中配置,如配置引用log庫:
defaultConfig { ndk { ldLibs "log" moduleName "myLib" //生成的so名字 abiFilters "armeabi", "armeabi-v7a", "x86" //輸出指定三種abi體系結構下的so庫。 } }
AS3.0(Gradle3.0)以上,android.useDeprecatedNdk=true已被棄用。須要使用CMake,在CMakeLists.txt中配置(CMakeLists.txt至關於MakeFile),在Build.gradle中:
defaultConfig{ // 使用Cmake工具 externalNativeBuild { cmake { cppFlags "" //生成多個版本的so文件 abiFilters 'arm64-v8a','armeabi-v7a','x86','x86_64' } } }
還須要在android節點中配置使用CMakeLists.txt:
// 配置CMakeLists.txt路徑 externalNativeBuild { cmake { path "CMakeLists.txt" // 設置所要編寫的c源碼位置,以及編譯後so文件的名字 } }
詳見:http://www.jb51.net/article/129667.htm
114.查看設備支持的ABI,須要使用adb shell 而後從屬性中讀取:
getprop | grep abilist //查看APK支持的ABI,使用aapt: ~ aapt dump badging sample.apk | grep abi //代碼中經過Build.SUPPORTED_ABIS或者手工讀取設備屬性也能夠查看設備支持的ABI。
115.AndroidStudio下載SDK源碼後沒法關聯,須要在 用戶/用戶名/.AndroidStudio版本號/config/options/jdk.table.xml中編輯對應SDK版本的sourcePath
屬性,指向源碼路徑,而後重啓AS便可。
116.Android JNI內存分配不受系統對單個應用的內存限制制約,能夠考慮經過JNI來作須要臨時申請大內存的事情。如加載大圖片。
117.當咱們從Launcher啓動一個應用程序時,實際的是在這個應用程序中Action和Category分別被配置爲MAIN和LAUNCHER的Activity。
這個Activity最終由ActivityManagerService通知其所在的進程進行啓動工做的,也就是經過ApplicationThread類的成員函數scheduleLaunchActivity開始執行
啓動工做的。其它類型的組件的啓動過程也是相似的。
118.Result不能跨Task返回。
119.Application,Activity,Service都直接或間接繼承自ContextWrapper,都會建立本身的Base Context,因此他們的Activity、Service與Application的BaseContext
是不一樣的,不過 getApplication()==getApplicationContext();
120.Android 5.0啓動或bind服務的Intent只支持顯式聲明瞭,即依然支持用類名聲明,可是使用Action聲明時,必定要配上PackageName,不然報IllegalArgumentException。
121.正如在Logcat中所見,Android中的進程是以包名命名的,子進程則會追加process指定的名字。判斷進程是不是主進程就能夠根據進程名判斷:
public static String getProcessName(Context context, int processId) { ActivityManager manager = (ActivityManager)context.getSystemService("activity"); List<RunningAppProcessInfo> processList = manager.getRunningAppProcesses(); if(processList != null && processList.size() > 0) { Iterator var4 = manager.getRunningAppProcesses().iterator(); while(var4.hasNext()) { RunningAppProcessInfo process = (RunningAppProcessInfo)var4.next(); if(process.pid == processId) { return process.processName; } } } return ""; }
122.Android HoneyComb(3.2)如下對SharedPreferences支持的Context.MODE_MULTI_PROCESS是經過監測文件變化從新加載實現的:
if ((mode & Context.MODE_MULTI_PROCESS) != 0 || getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) { // If somebody else (some other process) changed the prefs // file behind our back, we reload it. This has been the // historical (if undocumented) behavior. sp.startReloadIfChangedUnexpectedly(); }
123.J2ME中的getClass().getResourceAsStream在Android中一樣適用,可是須要注意資源存放路徑必須同類文件在一塊兒(也即經常使用的SRC目錄下。原理至關於類文件加載)。
Bitmap bitmap = BitmapFactory.decodeStream(getClass().getResourceAsStream("/res/drawable/ic_launcher.png")); Drawable drawable = new BitmapDrawable(getResources(), bitmap); //可是不能加載drawable-xhdpi這樣的目錄下的資源。
124.實現View的拖動,能夠在OnTouchEvent中改變View的LayoutParams,或者調用View的layout方法,還可使用ViewDragHelper幫助類。
125.Android WakeLock支持四種模式:
//Flag Value CPU Screen Keyboard PARTIAL_WAKE_LOCK On* Off Off SCREEN_DIM_WAKE_LOCK On Dim Off SCREEN_BRIGHT_WAKE_LOCK On Bright Off FULL_WAKE_LOCK On Bright Bright PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TimerService.class.getName()); wakeLock.acquire();
126.華爲系列手機上對未在白名單中的應用限制最大廣播註冊數500,超過則報錯java.lang.AssertionError:Register too many Broadcast Receivers,
可經過反射將報名加入到其白名單中。See:https://blog.csdn.net/llew2011/article/details/79054457
127.自定義Gradle plugin,使用Javassist(一個面向Java API編程的字節碼操做庫)修復第三方SDK代碼問題:https://blog.csdn.net/llew2011/article/details/78540911
128.ThreadLocal的神奇之處在於,它會自動依附於建立它的線程,就算是聲明爲靜態的,依然不會被類共享或者說覆蓋,每一個線程訪問到的依然是本身的
定義,這也是它最大的做用――經過它,每一個線程訪問同一個ThreadLocal變量獲得的是本身的定義。好比Looper的實現中,經過它爲每一個線程定義了
Looper引用:
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
129.Library中使用ButterKnife,須要在項目的Build.gradle中添加
buildscript { repositories { jcenter() mavenCentral() } dependencies { classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' classpath 'com.jakewharton:butterknife-gradle-plugin:8.4.0' } } //同時在Library的Build.gradle中添加 dependencies { compile 'com.jakewharton:butterknife:8.4.0' apt 'com.jakewharton:butterknife-compiler:8.4.0' }
而後在Library的註解中引用id時,要使用R2.id.xx 而非R.id.xx,固然代碼中使用時還得用R.id.xx
130.排除第三方庫中的庫引用:
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile("com.jude:easyrecyclerview:$rootProject.easyRecyclerVersion") { exclude module: 'support-v4'//根據組件名排除 exclude group: 'android.support.v4'//根據包名排除 } }
131.Gradle upload task
ext { PUBLISH_GROUP_ID = 'cn.dev' PUBLISH_ARTIFACT_ID = 'core' PUBLISH_VERSION = android.defaultConfig.versionName } uploadArchives { repositories.mavenDeployer { def deployPath = file(getProperty('aar.deployPath')) repository(url: "file://${deployPath.absolutePath}") pom.project { groupId project.PUBLISH_GROUP_ID artifactId project.PUBLISH_ARTIFACT_ID version project.PUBLISH_VERSION } } }
132.IDEA Project Structer沒有添加NDK Path的地方,直接在local.properties中添加NDK路徑便可。
133.View 不能設置顏色selector爲background,不然運行時會報Error inflating錯誤。設置單個顏色爲background沒有問題。
134.(實際驗證在xml Preview時生效,在設備上無效,layer-list不能達到縮小icon的目的)經過layer-list能夠將已有Icon縮小到指定尺寸,若是有大版本的Icon,須要小Icon時就不用切圖佔用空間了,用來在TextView上設置圖標時頗有用。
135.RelativeLayout,ConstraintLayout等Flat佈局容器在引用依賴anchor時,根據child index遞增不能倒序依賴未聲明的id,即不能使用@id/xx,可是可使用@+id/xx,不然編譯不過。
136.自定義屬性時,attrs中能夠定義取值類型爲enum和flags,兩者區別在於enum取值惟一,flags則能夠按位或,設置多個值。
137.Merge能夠做用於任意的佈局(而不只限於FrameLayout),用於減小多餘的相同的容器。
138.不一樣的編譯版本使用不一樣的資源,能夠分別爲不一樣版本在src中創建文件目錄。默認已有src/main,能夠創建src/debug對應debug編譯版本。(驗證代碼、applicationid)
139.使用CardView能夠對(圓角)矩形背景增長陰影效果
140.MD 按鈕點擊效果,即波紋效果,將View的背景設置爲"?android:attr/selectableItemBackground"或者"?android:attr/selectableItemBackgroundBorderless"便可。也可使用ripple節點自定義drawable做爲背景實現該效果。
141.View 縮放後原點(即左上角的座標點)會發生變化,計算新的原點應該偏移掉縮小的部分的二分之一(比例應該根據動畫中心點計算)。
142.RecyclerView利用payload能夠對一個Item作局部刷新,payload用開發者本身定義,指定不一樣的payload應該更新的部分,而後在onBindViewHolder(ViewHolderholder, int position, List<Object> payloads)中處理:
@Override public void onBindViewHolder(ViewHolderholder, int position, List<Object> payloads) { if (payloads.isEmpty()) { // payloads 爲 空,說明是更新整個 ViewHolder onBindViewHolder(holder, position); } else { int type= (int) payloads.get(0);// 刷新哪一個部分 標誌位 switch(type){ case 0: contact.userName.setText(mList.get(position).getName());//只刷新userName break; case 1: contact.userId.setText(mList.get(position).getId());//只刷新userId break; case 2: contact.userImg.setImageResources(mList.get(position).getImg());//只刷新userImg break; } } }
143.在onTouch(View v, MotionEvent event)中,event的getX()和get()容易受AXIS_X(Touch中心的屏幕X座標位置)和AXIS_Y(Touch中心得屏幕Y座標位置)的影響發生抖動,特別在平移和縮放View時容易出現,此時使用getRawX()和getRawY()能夠避免。
144.TransitionDrawable 能夠快捷實現兩張圖片的漸變顯示:第一張圖片漸隱,第二張圖片漸顯,不須要在最後同時顯示時,設置setCrossFadeEnabled(true)便可。
145.FragmentManager保存狀態,View/Fragment保存狀態(OnSaveInstanceState())。
(1)Activity會在容易被銷燬時調用OnSaveInstanceState(),如應用退回到後臺,Activity啓動了新的Activity,橫豎屏切換等;
(2)使用RatainedFragment,即在Fragment的onCreate()中調用setRetainInstance(true),能夠保存Fragment,避免在ConfigChanged過程當中重建,跳過onCreate()和onDestroy()。同時還能夠用一個NonUI的Fragment來
保存如緩存、線程等無需重建的數據或資源。(See:http://www.cnblogs.com/kissazi2/p/4116456.html)
(3)View.onSaveInstanceState()能夠用來保存View的臨時狀態,如TextView的當前光標位置,ListView的select position等。
146.Sqlite attach 將其餘數據庫附加到當前數據庫連接,可實現跨庫訪問和操做:http://www.sqlitetutorial.net/sqlite-attach-database/
db.execSQL("ATTACH DATABASE '" + DB_PATH + "' AS " + DB_ALIAS);
newDB.execSQL("DETACH DATABASE " + DB_ALIAS);
147.Sql語句中,REPLACE INTO 實現 insert or update 功能。
148.PRAGMA table_info(TABLE_NAME) 能夠返回表結構,官文描述;
// This pragma returns one row for each column in the named table. Columns in the result set include the column name, data type, whether or not the column can be NULL, and the default value for the column. The "pk" column in the result set is zero for columns that are not part of the primary key, and is the index of the column in the primary key for columns that are part of the primary key.
//
// The table named in the table_info pragma can also be a view.
對於Attach的數據庫,須要這樣調用:
PRAGMA DB_ALIAS.table_info(TABLE_NAME)
149.GreenDao支持自定義類型轉換,表中可定義自定義類型的Column,添加並實現Converter轉換成Sqlite類型便可,可參考:http://greenrobot.org/greendao/documentation/custom-types/
@Convert(converter = RoleConverter.class, columnType = String.class) private Role role;
150.View.getHitRect()能夠返回View相對於Parent的響應區域,可用於判斷MotionEvent是否發生在指定的View上。
151.Glide返回的Bitmap是Immutable bitmap,不能隨意釋放,也不能用於作高斯模糊,若是須要,能夠建立一個圖片副本再作效果。
152.GreenDao中StringCondition用來支持更爲複雜的查詢,如比較兩個字段的值,下面的例子比較消息讀取時間和消息接收時間:
queryBuilder.where(new WhereCondition.StringCondition(ConversationDao.Properties.LastReadAt.columnName + " < " + ConversationDao.Properties.LastRecvAt.columnName));
153.AsyncTask的任務隊列最多支持128個任務:
private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128);
154.android:process做用於application時,能夠爲應用(的全部組件)指定一個進程來運行。做用於四大組件時,組件會在指定的進程中運行。它的取值也須要注意,當以":"開頭時,應用將會爲指定的組件建立私有進程;當以一個小寫字母開頭時,將會使用以這個命名的全局進程來運行對應的組件,這樣能夠容許多個應用使用同一個進程已達到減小資源使用的效果(前提是這些應用共享相同的 Linux 用戶 ID 並使用相同的證書進行簽署)。適用於SDK開發時使用。
155.android:multiprocess,可做用於activity和provider,用於賦予組件在使用到它的其餘進程建立實例的能力。一般用於provider,使得在使用到的進程建立Provider實例而避免IPC操做。
156.ViewPager remove item 或者改變Item內部狀態後由於View緩存不會實時更新設置顯示異常,最好的辦法是重寫PagerAdapter的getItemPosition方法,對於須要更新的
Item返回PagerAdapter.POSITION_NONE,會促使ViewPager在notifyDatasetChange時爲該元素從新生成View,其餘元素返回其更新後的位置,爲了對效率進行優化,能夠在Item數據中緩存position,並在改變是更新,這樣在getItemPosition中就能夠直接進行返回。對於動態內容,如媒體播放,在remove後須要從新觸發一次播放。(若是Remove發生在PageChange一秒以內,頁面可能體驗很差,能夠用Delay來修復)Snippet:
private void removeModel(final BaseMomentPlayModel model) { ... List<BaseMomentPlayModel> list = mMomentList; list.remove(model); int size = list.size(); int position = model.position; for (; position < size; position++) { //Update position. list.get(position).position = position; } //Mark as changed. model.position = PagerAdapter.POSITION_NONE; if (mMoment == model) { mMoment = null; mViewPager.post(new Runnable() { @Override public void run() { //Restart playback setCurrentPage(mViewPager.getCurrentItem(), false); } }); } reattachAdapter(); } @Override public int getItemPosition(@NonNull Object object) { View view = (View) object; BaseMomentPlayModel model = (BaseMomentPlayModel) view.getTag(); return model.position; }
157.用MessageQueue能夠實現懶加載方式,封裝須要懶執行的任務到IdleHandler,添加到MessageQueue,在空閒的時候便會執行
Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() { @Override public boolean queueIdle() { //Do something to be lazily done. return false; } });