日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

不删除侦听器–使用ListenerHandles

發(fā)布時(shí)間:2023/12/3 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 不删除侦听器–使用ListenerHandles 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

聽一個(gè)可觀察的實(shí)例并對(duì)它的變化做出反應(yīng)很有趣。 做一些必要的事情來打斷或結(jié)束這種聆聽會(huì)變得很有趣。 讓我們看看問題的根源和解決方法。

總覽

這篇文章將首先討論這種情況,然后再討論常見的方法和問題所在。 然后,它將提供解決大多數(shù)問題的簡(jiǎn)單抽象。

盡管示例使用Java,但許多其他語言也存在缺陷。 提出的解決方案可以應(yīng)用于所有面向?qū)ο蟮恼Z言。 那些懶于自己在Java中實(shí)現(xiàn)抽象的人可以使用LibFX 。

情況

由Ky Olsen在CC-BY 2.0下發(fā)布 。

假設(shè)我們想聽聽屬性值的變化。 這很簡(jiǎn)單:

不支持刪除的簡(jiǎn)單案例

private void startListeningToNameChanges(Property<String> name) {name.addListener((obs, oldValue, newValue) -> nameChanged(newValue)); }

現(xiàn)在假設(shè)我們要在特定間隔內(nèi)中斷監(jiān)聽或完全停止監(jiān)聽。

保持參考

解決此問題的最常見方法是保留對(duì)偵聽器的引用,并保留對(duì)周圍屬性的引用。 根據(jù)具體的用例,實(shí)現(xiàn)會(huì)有所不同,但是它們都可以歸結(jié)為以下形式:

默認(rèn)方式刪除偵聽器

private Property<String> listenedName; private ChangeListener<String> nameListener;...private void startListeningToNameChanges(Property<String> name) {listenedName = name;nameListener = (obs, oldValue, newValue) -> nameChanged(newValue);listenedName.addListener(nameListener); }private void stopListeningToNameChanges() {listenedName.removeListener(nameListener); }

盡管這看起來不錯(cuò),但我確信這實(shí)際上是一個(gè)糟糕的解決方案(盡管是默認(rèn)解決方案)。

首先,額外的引用使代碼混亂。 很難讓他們表達(dá)出為什么要留在身邊的意圖,因此它們降低了可讀性。

其次,它們通過向類添加新的不變式來增加復(fù)雜性:該屬性必須始終是添加了偵聽器的屬性。 否則,對(duì)removeListener的調(diào)用將無提示地執(zhí)行任何操作,并且在將來的更改時(shí)仍將執(zhí)行該偵聽器。 放開這可能是討厭的。 如果類很短,則堅(jiān)持不變性是容易的,但如果變得越來越復(fù)雜,則可能成為問題。

第三,引用(尤其是該屬性的引用)邀請(qǐng)與它們進(jìn)行進(jìn)一步的交互。 這可能不是故意的,但沒有任何辦法阻止下一個(gè)開發(fā)人員繼續(xù)這樣做(請(qǐng)參閱第一點(diǎn))。 而且,如果有人確實(shí)開始對(duì)該物業(yè)進(jìn)行操作,第二點(diǎn)將成為非?,F(xiàn)實(shí)的風(fēng)險(xiǎn)。

這些方面已經(jīng)使它無法成為默認(rèn)解決方案。 但是還有更多! 在許多類中必須這樣做會(huì)導(dǎo)致代碼重復(fù)。 最后,上面的實(shí)現(xiàn)包含一個(gè)競(jìng)爭(zhēng)條件。

偵聽器句柄

大多數(shù)問題來自直接在需要中斷/結(jié)束偵聽的類中處理可觀察對(duì)象和偵聽器。 這是不必要的,所有這些問題都可以通過一個(gè)簡(jiǎn)單的抽象來解決: ListenerHandle 。

ListenerHandle

public interface ListenerHandle {void attach();void detach(); }

ListenerHandle保留對(duì)可觀察對(duì)象和偵聽器的引用。 在調(diào)用attach()或detach()它要么將偵聽器添加到可觀察對(duì)象,要么將其刪除。 為了將此語言嵌入語言,當(dāng)前將偵聽器添加到可觀察對(duì)象的所有方法都應(yīng)返回該組合的句柄。

現(xiàn)在剩下要做的就是針對(duì)所有可能的情況實(shí)際實(shí)現(xiàn)句柄。 或者說服那些開發(fā)您喜歡的編程語言的人來做。 這留給讀者練習(xí)。

注意,這解決了上面提到的所有問題,除了爭(zhēng)用條件之外。 有兩種解決方法:

  • 處理實(shí)現(xiàn)可能本質(zhì)上是線程安全的
  • 可以實(shí)現(xiàn)一個(gè)同步裝飾器

LibFX中的ListenerHandles

作為Java開發(fā)人員,您可以使用LibFX ,它支持三個(gè)級(jí)別的偵聽器句柄。

功能了解ListenerHandles

添加偵聽ListenerHandle時(shí), LibFX的所有可實(shí)現(xiàn)此功能而不與Java API沖突的功能都會(huì)返回一個(gè)ListenerHandle 。

以WebViewHyperlinkListener為例:

將“ ListenerHandle”獲取到“ WebViewHyperlinkListener”

WebView webView;ListenerHandle eventProcessingListener = WebViews.addHyperlinkListener(webView, this::processEvent);

JavaFX實(shí)用程序

由于LibFX與JavaFX有緊密的聯(lián)系(可能會(huì)想到!),它提供了一個(gè)實(shí)用程序類,該類將偵聽器添加到可觀察對(duì)象并返回句柄。 這適用于JavaFX中存在的所有可觀察/偵聽器組合。

例如,讓我們看一下ObservableValue<T> / ChangeListener<? superT>的組合ChangeListener<? superT> ChangeListener<? superT> :

'ListenerHandles'中的一些方法

public static <T> ListenerHandle createAttached(ObservableValue<T> observableValue,ChangeListener<? super T> changeListener);public static <T> ListenerHandle createDetached(ObservableValue<T> observableValue,ChangeListener<? super T> changeListener);

ListenerHandleBuilder

在所有其他情況下,即對(duì)于上面未涵蓋的任何可觀察/偵聽器組合,可以使用構(gòu)建器來創(chuàng)建手柄:

為自定義類創(chuàng)建“ ListenerHandle”

// These classes do not need to implement any special interfaces. // Their only connection are the methods 'doTheAdding' and 'doTheRemoving', // which the builder does not need to know about. MyCustomObservable customObservable; MyCustomListener customListener;ListenerHandles.createFor(customObservable, customListener).onAttach((obs, listener) -> obs.doTheAdding(listener)).onDetach((obs, listener) -> obs.doTheRemoving(listener)).buildAttached();

反應(yīng)式編程

雖然這不是關(guān)于反應(yīng)式編程的文章 ,但仍應(yīng)提及。 查看ReactiveX (用于許多語言,包括Java,Scala,Python,C ++,C#和更多語言)或ReactFX (或此介紹性文章 )以了解一些實(shí)現(xiàn)。

反射

我們已經(jīng)看到,從可觀察對(duì)象中刪除偵聽器的默認(rèn)方法會(huì)產(chǎn)生許多危害,需要避免。 偵聽器句柄抽象提供了解決許多問題的干凈方法,而LibFX提供了一種實(shí)現(xiàn)。

翻譯自: https://www.javacodegeeks.com/2015/01/dont-remove-listeners-use-listenerhandles.html

總結(jié)

以上是生活随笔為你收集整理的不删除侦听器–使用ListenerHandles的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。