AllenHsu的技術手扎

學海無涯,努力做個永遠年輕的人

NSTimer 的 retain cycle 的問題

有時我們常常需要在 Controller 中建立一個定時被呼叫的函數,所以會使用到 NSTimer,NSTimer 很容易產生 retain cycle 的狀況,下列一個是很常見的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class ViewController: UIViewController {

var timer : Timer?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(fire), userInfo: nil, repeats: false)
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

@objc func fire() {
//Do some thing
}

deinit {
timer?.invalidate()
timer = nil;
}
}
Read more »

RecycleView的Bug : java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position

最近在工作上,因為某些原因,需要很快速地刷新RecycleView內的元素,但是很常出現閃退,追了一下log,發現是下列的原因:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 150(offset:150).state:153
at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5504)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5440)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5436)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2224)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1551)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1511)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:595)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3583)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3312)
at android.support.v7.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1618)
at android.support.v7.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:4702)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
at android.view.Choreographer.doCallbacks(Choreographer.java:686)
at android.view.Choreographer.doFrame(Choreographer.java:619)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7409)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

Bug 出現原因 :

再進行數據變動時,務必要保證 Adapter 中的數據和移除的數據保持一致,就是當你更新你的集合後,呼叫 notify 方法時, adapter 的更新預期結果和實際集合更新結果不同,就會出現此異常。

例如: 增加了兩條數據,但是 Adapter 的 notify 只增加 5 條數據,這種情況就屬於不一致,簡單來說 Apapter 有個 Size,你的資料結構集合也有 Size,這兩個 Size 在呼叫 notify 方法時必須保持相同。

解決方法 :

覆寫 xxxxLayoutManager(看你使用的是 LinearLayoutManager 或是 GridLayoutManager或其他)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class RecyclerViewLinearLayoutManager extends LinearLayoutManager {
public RecyclerViewLinearLayoutManager(Context context) {
super( context );
}

public RecyclerViewLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super( context, orientation, reverseLayout );
}

public RecyclerViewLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super( context, attrs, defStyleAttr, defStyleRes );
}

@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
try {
//主要在這邊加入 try catch
super.onLayoutChildren( recycler, state );
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
}

}
}

主要是在添加集合的時候,增加了一層 try catch去解決。

參考 :

https://stackoverflow.com/questions/30458640/recyclerview-java-lang-indexoutofboundsexception-inconsistency-detected-inval

http://www.cnblogs.com/fuyaozhishang/p/6991221.html

前言

前面介紹了關於 RxSwift 的資源管理,這次要來介紹關於 RxJava 的部分,在 RxJava 中有一些第三方的資源管理像是 RxLifecycle 這種好用的第三方庫來幫忙在程式碼中,如果沒有及時的回收 Rx 相關的資源,會造成 Activity/Fragment 無法銷毀所導致的 Memory LeakRxLifecycle 的用法就是讓我們的 Observable 跟隨著 Activity/Fragment 的生命週期去取消訂閱,但是這樣就真的完美解決了 RxJava 的記憶體管理問題嗎 ? 我們來看看 RxLifecycle 的作者怎麼說。

Read more »

關於 RxSwift 的記憶體管理機制

在介紹關於 RxSwift 基本入門 中提到了一些 RxSwift 的核心概念 - Observable ,我們描述了事件訊息的種類,分別是 : nexterrorcompleted , 當這個 Observable 收到errorcompleted 事件訊息時,那麼這個 Observable 將不會再接受其他的訂閱事件。 同時在這邊用來分派給此 Observable 的記憶體資源就一起被釋放掉了,我們可以將其視為類似 ARC 的自動記憶體釋放。 如果你想立刻將 Observable 關閉且立刻釋放資源,那麼你需要呼叫 dispose 函數,這邊我們可以理解為類似 MRC 的手動釋放。

如果一個 Observable 在一定的時間內結束,即使不呼叫 dispose 或者使用 DisposeBag 也不會引發 Memory Leak。 如果一個 Observable 因為某些原因

沒有結束,那記憶體將會永遠的不會被釋放,所以就算 根據 Observable 的運作原理,我們也會希望透過某些記憶體回收機制來確保不會產生 Memory Leak 的問題。

下面將詳細介紹幾種 RxSwift 的記憶體管理機制。

Read more »

RxSwift 初心者入門

在之前我們稍微提過 RxSwift 這一個 framework ,也有稍微介紹了什麼是 Reactive Programming ,那這邊就來詳細談談如何學習以及使用 RxSwfit 吧。

使用 RxSwift 的 Playground

首先我們先至 RxSwift Clone 整個 Project,接著我們這邊使用 Rx.Playground 做為入門的教學,按照官網的操作如下

1
2
3
4
5
6
To use playgrounds:

Open Rx.xcworkspace
Build the RxSwift-macOS scheme
Open Rx playground in the Rx.xcworkspace tree view.
Choose View > Debug Area > Show Debug Area
Read more »

為什麼需要規範團隊的 git log

在團隊開發中,我們常常會希望團隊遵循一個 git commit log 的規範,原因是我們希望在未來要查找之前的 log 時,可以透過這樣的方式可以很快的搜尋到想要的結果,也可以在 CI/CD 的流程中,透過規範的 git log 藉而產出一個有意義且能給 QA/PM/其他團隊成員觀看的 CHNAGELOG (版本更新內容)

Read more »

RecyclerView - 比 ListView 更強大易用效率高的滾動元件

雖然 ListView 可以完成我們大部分列表的需求,不過我們需要使用額外的方式來提高 ListView 的效率,然後 ListView 的擴展性也還不夠全面,它無法做到橫向滾動的效果,所以 Android 提供了一個更強大的元件 — RecyclerView

Read more »

ListView - 如何提高執行效能

在 ListView 中,如何有效的提高執行效能是很重要的一點,它有相當多的細節可以優化,這邊會介紹該如何去提高執行的效能。

Read more »

ListView - 定製介面

上一篇文章中,我們介紹了基本的 ListView 用法, 但是我們在專案中,常常會需要不只是顯示文字,而是圖片或者其他更豐富的 ListView 介面。

Imgur

Read more »

Android 最常用和最難用的 UI 元件 - ListView

ListView 絕對是 Android開發中最常用的 UI 元件之一,幾乎所有的應用程序都會用到它,當我們需要顯現大量數據的時候,我們就需要借助 ListView 來實現。比如說觀察 FB、IG 的 Po 文…等等

Imgur

Read more »
0%