Java基礎
public synchronized void run() {
System.out.println(1);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println(2);
}
複製代碼
Demo demo = new Demo();
new Thread(() -> demo.run()).start();
Demo demo2 = new Demo();
new Thread(() -> demo2.run()).start();
複製代碼
結果爲: 1 1 2 2java
不一樣步。但若是使用同一對象訪問,結果纔是同步的node
Demo demo = new Demo();
new Thread(() -> demo.run()).start();
new Thread(() -> demo.run()).start();
複製代碼
輸出結果:1 2 1 2android
final關鍵字用於基本數據類型前:這時代表該關鍵字修飾的變量是一個常量,在定義後該變量的值就不能被修改。
final關鍵字用於方法聲明前:這時意味着該方法時最終方法,只能被調用,不能被覆蓋,可是能夠被重載。
final關鍵字用於類名前:此時該類被稱爲最終類,該類不能被其餘類繼承。算法
用try{ }catch(){} 捕獲異常時,不管室友有異常,finally代碼塊中代碼都會執行。sql
finalize方法來自於java.lang.Object,用於回收資源。 能夠爲任何一個類添加finalize方法。finalize方法將在垃圾回收器清除對象以前調用數據庫
if(JVM內存不足) {
// 將軟引用中的對象引用置爲null
str = null;
// 通知垃圾回收器進行回收
System.gc();
}
複製代碼
還在用Synchronized?Atomic你瞭解不?apache
多線程併發問題編程
try{
new Thread(){
public void run(){
if (...) throw new RuntimeException();
}
}.start();
}catch(Exception e){
}
複製代碼
答案不能。設計模式
因此線程方法的異常只能本身來處理,線程的問題應該線程本身自己來解決,而不要委託到外部數組
Android基礎知識
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
複製代碼
爲了解決多個線程訪問同一個數據問題,同步鎖的思路是線程不能同時訪問一片內存區域.而ThreadLocal的思路是,乾脆給每一個線程Copy一份一摸同樣的對象,線程之間各自玩本身的,互相不影響對方 常見ThreadLocal應用場景:確保在每個線程中只有一個Looper的實例對象
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
複製代碼
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
複製代碼
簡而言之:先拿到當前線程,再從當前線程中拿到ThreadLocalMap,經過ThreadLocalMap來存儲數據。(ThreadLocalMap是Thread的成員變量)
Activity對事件響應不超過5秒,BroadcastReceiver執行不超過10秒,Service耗時操做爲20秒。不然系統會報ANR
FragmentPageAdapter在每次切換頁面的的時候,沒有徹底銷燬Fragment,適用於固定的,少許的Fragment狀況。默認notifyDataSetChanged()刷新是無效的
FragmentPageStateAdapter在每次切換頁面的時候,是將Fragment進行回收,適合頁面較多的Fragment使用,這樣就不會消耗更多的內存
事務是由一個或多個sql語句組成的一個總體,若是全部語句執行成功那麼修改將會所有生效,若是一條sql語句將銷量+1,下一條再+1,假若第二條失敗,那麼銷量將撤銷第一條sql語句的+1操做,只有在該事務中全部的語句都執行成功纔會將修改加入數據庫中
sqlite數據庫相關操做,主要包括建立和增刪改查,事務
ViewGroup
的onInterceptTouchEvent
默認返回false,即不攔截事件,View
沒有攔截事件方法,View
默認時消耗事件的ViewGroup
默認不會調用onDraw方法,View
默認會調用onDraw方法。能夠經過setWillNotDraw(boolean willNotDraw)
來指定是否調用onDraw方法/** * If this view doesn't do any drawing on its own, set this flag to * allow further optimizations. By default, this flag is not set on * View, but could be set on some View subclasses such as ViewGroup. * * Typically, if you override {@link #onDraw(android.graphics.Canvas)} * you should clear this flag. * * @param willNotDraw whether or not this View draw on its own */
public void setWillNotDraw(boolean willNotDraw) {
setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
}
複製代碼
android {
useLibrary 'org.apache.http.legacy'
}
複製代碼
Android框架知識
經過註解處理器動態生成java文件,在java文件中進行findViewById和setOnClickListener操做
經過觀察者設計模式,先經過註冊的方式將指定的類加到一個表裏面,等發送消息時輪訓那個表,依據註解和註解的value找到匹配的方法,而後執行該方法
LiveData通知其餘組件原理主要是觀察者設計模式。其優勢有
簡單來講,就是可讓你本身的類擁有像 activity 或 fragment 同樣生命週期的功能。繼承Lifecycle 的組件將生命週期脫離出 activity 而轉到本身身上
使用步驟:
(1) 繼承DefaultLifecycleObserver
class TestObserver implements DefaultLifecycleObserver {
@Override
public void onCreate(LifecycleOwner owner) {
// your code
}
}
複製代碼
(2) LifecycleOwner是隻有一個方法getLifecycle()的接口,是讓擁有生命週期的東西實現好比(activity)用來獲取Lifecycle。在Android Support Library 26.1.0 及其以後已經activity 和 fragment 已經默認實現了LifecycleOwner 因此在 activity 裏咱們能夠直接:
getLifecycle().addObserver(new MyObserver());
複製代碼
這樣咱們的MyObserver就會感知 activity 的生命週期了
Flowable
和Observable
RxJava1中使用Observable
和Observer
創建起訂閱關係,但會產生背壓問題。Rxjava2使用Flowable
和Subscriber
替換RaJava1的Observable
和Observer
。Flowable
是在Observable
的基礎上優化後的產物,Observable
能解決的問題Flowable
也都能解決。可是並不表明Flowable
能夠徹底取代Observable
,Flowable
運行效率要比Observable
慢得多。 只有在須要處理背壓問題時,才須要使用Flowable
Rxjava容易遭層內存泄漏。在訂閱了事件後沒有及時取閱,致使在activity或者fragment銷燬後仍然佔用着內存,沒法釋放。而disposable,能夠用來取消訂閱
參考Rxjava關於Disposable你應該知道的事
設計模式
1.MVC
Android傳統就是用MVC模式,Modle(邏輯)和V(View)直接交互,耦合度過高,MVC中是容許Model和View進行交互的,而MVP中很明顯,Model與View之間的交互由Presenter完成。還有一點就是Presenter與View之間的交互是經過接口的
2.MVP
當View 須要更新數據時,首先去找 Presenter,而後 Presenter 去找 Model 請求數據,Model 獲取到數據以後通知 Presenter,Presenter 再通知 View 更新數據,這樣 Model 和 View就不會直接交互了,全部的交互都由 Presenter 進行,Presenter 充當了橋樑的角色。很顯然,Presenter 必須同時持有 View 和 Model 的對象的引用,才能在它們之間進行通訊
解決辦法:
在Presenter中使用弱引用,將view的引用加到弱引用中去 每一個Activity都有BaseActivity,BaseActivity中
3.MVVM
經過雙向綁定的機制
算法
Node node4 = new Node(4, null);
Node node3 = new Node(3, node4);
Node node2 = new Node(2, node3);
Node node1 = new Node(1, node2);
Node pHead = node1;//頭結點
複製代碼
這組鏈表從1到4排序,要求反轉後4到1
public static Node reverseList(Node pHead) {
Node pReversedHead = null; //反轉事後的單鏈表存儲頭結點
Node pNode = pHead; //當前節點
Node pPrev = null; //前一結點
while (pNode != null) {
//1.記錄next,下一步:更新當前節點的上一節點和自己。最後移動一位
Node pNext = pNode.next;
if (pNext == null) {
//到了尾節點
pReversedHead = pNode;
}
pNode.next = pPrev;
pPrev = pNode;
pNode = pNext;
}
return pReversedHead;
}
複製代碼
輸出
pHead = reverseList(pHead);//反轉以後頭結點
while (pHead != null) {
System.out.println(pHead.key);
pHead = pHead.next;
}
複製代碼