1.View的post():
可以保證在UI線程中進(jìn)行需要的操作,方便地進(jìn)行異步通信。將任務(wù)交由attachInfo中的Handler處理,
保證在UI線程執(zhí)行。本質(zhì)上是依賴于以Handler、Looper、MessageQueue、Message為基礎(chǔ)的異步消息處理機(jī)制。
所以post方法相當(dāng)于把這個(gè)事件添加到了UI 事件隊(duì)列中。
比如在onCreate方法中獲取某個(gè)view的寬高,而直接View#getWidth獲取到的值是0。
View顯示到界面上需要經(jīng)歷onMeasure、onLayout和onDraw三個(gè)過(guò)程,而View的寬高是在onLayout階段才能最終確定的。
而在onCreate中并不能保證View已經(jīng)執(zhí)行到了onLayout方法,也就是說(shuō)Activity的聲明周期與View的繪制流程并不是一一綁定。
那為什么調(diào)用post方法就能起作用呢?
首先MessageQueue是按順序處理消息的,而在setContentView()后隊(duì)列中會(huì)包含一條詢問(wèn)是否完成布局的消息,
而我們的任務(wù)通過(guò)View#post方法被添加到隊(duì)列尾部,保證了在layout結(jié)束以后才執(zhí)行。
調(diào)用View.post()既方便又可以保證指定的任務(wù)在視圖操作中順序執(zhí)行。
2.targetView.getViewTreeObserver().addOnGlobalLayoutListener(…)
作用范圍是頁(yè)面級(jí)的大布局,而且整個(gè)activity只需要有一個(gè)整個(gè)view樹(shù)的監(jiān)聽(tīng)就行了。
設(shè)置了OnGlobalLayoutListener之后,要在回調(diào)中馬上去掉這個(gè)監(jiān)聽(tīng)。不然會(huì)回調(diào)很多遍,OnPreDrawListener也是如此
mJobChooseTv.getViewTreeObserver().removeOnGlobalLayoutListener(this);
在整個(gè)監(jiān)聽(tīng)里,也可以獲得寬高。
3.visibility=gone肯定不會(huì)繪制,顯示的時(shí)候不會(huì)占布局空間。onMeasure、onLayout、onDraw三個(gè)方法都不會(huì)走。
visibility=isvisible不會(huì)繪制,顯示的時(shí)候會(huì)占布局空間。會(huì)走onMeasure、onLayout。不會(huì)走onDraw。
view的可見(jiàn)性從GONE設(shè)置為VISIBLE時(shí)會(huì)申請(qǐng)requestLayout,而layout是異步執(zhí)行的,
所以setVisibility方法返回了但是該操作還未完成。
4.反射:可以實(shí)現(xiàn)在運(yùn)行時(shí)知道任意一個(gè)類的屬性和方法
(1)獲取到Class對(duì)象。
Class<?> setLogTaskClass=setLogTaskClass = Class.forName("com.job.android.statistics.SetLogTask");
三種方法:
通過(guò)Person的對(duì)象,person.getClass()
Person.class
Class.forName(Person的全路徑包名)
(2)獲取構(gòu)造函數(shù)
Constructor<?> constructor=setLogTaskClass.getConstructor(String.class,String.class);
(3)創(chuàng)建對(duì)象
Object object=constructor.newInstance("deeplink",param.getString("deeplinkid"));
//原來(lái)的構(gòu)造方法是需要傳入兩個(gè)string參數(shù):public SetLogTask(String type, String event)
可以像上面在獲取構(gòu)造函數(shù)之后創(chuàng)建對(duì)象,也可以獲取到了Class之后創(chuàng)建對(duì)象,但只能通過(guò)無(wú)參構(gòu)造函數(shù)來(lái)創(chuàng)建
Class personClazz = Class.forName(com.example.Person);
Object person = personClazz.newInstance();
(4)獲取方法
Method method1=setLogTaskClass.getMethod("executeOnPool",null);
executeOnPool為方法名,null為參數(shù)??梢垣@得父類的方法
(5)通過(guò)invoke方法調(diào)用方法,第一個(gè)參數(shù)是實(shí)例對(duì)象,后面的是參數(shù)。
method1.invoke(object,null);
(6)獲取屬性及其他
getField(String name)
void setAccessible(boolean flag)//啟用和禁用訪問(wèn)安全檢查的開(kāi)關(guān),true為取消Java 語(yǔ)言訪問(wèn)檢查。
getAnnotation(Class<T> annotationClass) //獲取屬性或者方法或者類上的注解
具體如下:
Class clazz = null;
//(1)獲取到Class對(duì)象。
clazz = Class.forName("com.example.viewpageradapter.Person");
//(2)獲取構(gòu)造函數(shù)
Constructor<?> constructor=clazz.getDeclaredConstructor(String.class,int.class);
//(3)創(chuàng)建對(duì)象
Object object=constructor.newInstance("我是疾風(fēng)劍豪",18);
//(4)獲取方法
Method method=object.getClass().getMethod("setLog",null);
//(5)通過(guò)invoke方法調(diào)用方法,第一個(gè)參數(shù)是實(shí)例對(duì)象,后面的是參數(shù)
method.invoke(object,null);
//(6)獲取屬性及其他
Field field=object.getClass().getDeclaredField("number");
Field field1=object.getClass().getDeclaredField("name");
//(7)獲取成員變量的值
String name= (String) field1.get(object);
int number= (int) field.get(object);
Log.i(TAG, "getReflect--name是: "+ name +", number是:"+ number);
public class Person {
private String name;
private int number;
public Person() {
}
public Person(String name,int number){
this.name = name;
this.number=number;
}
public void setLog(){
Log.i("Main3Activity_log", "setLog: 這是Person類中打印出的log"+name+number);
}
}
5.兩個(gè)方法的區(qū)別:
執(zhí)行execute(): 線程可以只能串行運(yùn)行
執(zhí)行executeOnExecuter(): 線程并行運(yùn)行,不過(guò)同一時(shí)間只能啟動(dòng)五個(gè)線程
6.單例模式
public class Person {
//實(shí)現(xiàn)單例模式, 線程每次使用到被volatile關(guān)鍵字修飾的變量時(shí),都會(huì)去堆里拿最新的數(shù)據(jù)
private volatile static Person instance;
/*第一次判斷是為了避免不必要的同步,
第二次判斷是確保在此之前沒(méi)有其他線程進(jìn)入到sychronized塊創(chuàng)建了新實(shí)例。*/
public static Person getInstance() {
if (instance == null) {
synchronized (Person.class) {
if (instance == null) {
instance = new Person();
}
}
}
return instance;
}
//將默認(rèn)的構(gòu)造函數(shù)私有化,防止其他類手動(dòng)new
private Person() {
}
}
7.深淺拷貝
淺拷貝:對(duì)基本數(shù)據(jù)類型進(jìn)行值傳遞,對(duì)引用數(shù)據(jù)類型進(jìn)行引用傳遞般的拷貝,此為淺拷貝。
深拷貝:對(duì)基本數(shù)據(jù)類型進(jìn)行值傳遞,對(duì)引用數(shù)據(jù)類型,創(chuàng)建一個(gè)新的對(duì)象,并復(fù)制其內(nèi)容,此為深拷貝。
實(shí)則淺拷貝和深拷貝只是相對(duì)的,如果一個(gè)對(duì)象內(nèi)部只有基本數(shù)據(jù)類型,那用 clone() 方法獲取到的就是這個(gè)對(duì)象的深拷貝,
而如果其內(nèi)部還有引用數(shù)據(jù)類型,那用 clone() 方法就是一次淺拷貝的操作。
如果再對(duì)這個(gè)對(duì)象內(nèi)部的引用數(shù)據(jù)類型進(jìn)行clone操作,那么就是深拷貝。
Person person=new Person();
person.name="ss";
person.number=2;
Person person1= (Person) person.clone();
Log.i("Main4Activity", "onCreate: "+person.hashCode()+", "+person1.hashCode());
一個(gè)對(duì)象內(nèi)部只有基本數(shù)據(jù)類型的對(duì)象,clone之后,從 == 和 hashCode 的不同可以看出,并不相等,所以
clone() 方法實(shí)則是真的創(chuàng)建了一個(gè)新的對(duì)象,所以這是深拷貝。
淺拷貝只是引用傳遞,不會(huì)新創(chuàng)建一個(gè)對(duì)象,所以他們的hashcode是一樣的。
8.單例、觀察者、工廠、原型、Builder模式
原型模式使用場(chǎng)景
(1)類初始化需要消化非常多的資源,這個(gè)資源包括數(shù)據(jù)、硬件資源等,通過(guò)原型拷貝避免這些消耗。
(2)通過(guò)new產(chǎn)生的一個(gè)對(duì)象需要非常繁瑣的數(shù)據(jù)準(zhǔn)備或者權(quán)限,這時(shí)可以使用原型模式。
(3)一個(gè)對(duì)象需要提供給其他對(duì)象訪問(wèn),而且各個(gè)調(diào)用者可能都需要修改其值時(shí),
可以考慮使用原型模式拷貝多個(gè)對(duì)象供調(diào)用者使用,即保護(hù)性拷貝。