英文:
Java/Android : shortest way (lambda?) to pass a target handler to a custom button referencing this as a weak reference
问题
在Android中,我创建了自定义按钮。以前,我只是有一个非常简单的界面来传递目标方法作为按钮的回调:
public interface onTouchInterface {
void onTouch();
}
当我想要将回调传递给按钮时,我只是使用了lambda表达式:
mybutton.addTarget(this::mycallback);
这是一种快捷方式,等同于:
mybutton.addTarget(new onTouchInterface() {
@Override
void onTouch() { this.mycallback() }
});
问题是,我发现this
(在我这种情况下通常是一个Fragment)在我从任何地方删除Fragment后仍然存在于内存中,尽管垃圾回收器应该已经将其删除。我发现它被我的lambda表达式“封装”起来。
我的问题是:如何在拥有弱引用的情况下编写最短的语法?目前,我创建了这个类来代替我以前的非常简单的接口:
public abstract static class Target<T>
{
protected WeakReference<T> scope;
static protected class ScopeNotPresentException extends Exception {}
protected Target(T scope) { this.scope = new WeakReference<T>(scope); }
// 这是按钮在用户点击时调用的原始回调
// 如果作用域为null,则引发异常,否则执行onTouch(可重写)
final public void onTouchRawCallback() throws ScopeNotPresentException {
if(scope.get() == null)
throw new ScopeNotPresentException();
else
onTouch(scope.get());
}
// 当执行这个子类化方法时,会验证作用域是否不为null
protected void onTouch(T scope) { }
}
我的按钮类原始回调如下:
try {
mTarget.onTouchRawCallback();
}
catch(Target.ScopeNotPresentException e){
Log.w(LOG_TAG, "target button method was ignored because scope weak ref is null");
}
因此,如果scope.get()
为null,则触发异常,不会调用onTouch()
。最后,所有我的Fragment都像这样为它们的按钮添加处理程序:
mybutton.addTarget(new MyCustomButton.Target<MyFragment>(this) {
@Override
protected void onTouch(MyFragment scope) {
scope.fragmentCustomClickHandler();
}
});
但这当然比mybutton.addTarget(this::mycallback);
要冗长得多。我发现对于带有传递给构造函数的参数的泛型类型的类,无法使用lambda。你有没有更好的实现方法,以便我可以继续使用lambda的简短语法,同时使用弱引用安全地检索this
?(例如,在Swift中,可以使用addTarget({ [weak self] self?.myCallback(); })
,如果self
为null,就会停止执行)
英文:
I created my custom buttons in Android. Before, I just had a very simple interface to pass target method as a callback for my buttons :
public interface onTouchInterface {
void onTouch();
}
When I wanted to pass a callback to a button, I just used lambda expression :
mybutton.addTarget(this::mycallback);
which is a shortcut for
mybutton.addTarget(new onTouchInterface() {
@Override
void onTouch() { this.mycallback() }
});
The problem is that I realized that this
(which is often a Fragment in my case) was still in the memory even after I removed my fragment from anywhere, while garbage collector should have removed it. I discovered it was "encapsuled" by my lambda expression.
My question is : how can I make the shortest syntax while having a weak reference for this ? For the moment, I created this class instead of my old very simple interface :
public abstract static class Target<T>
{
protected WeakReference<T> scope ;
static protected class ScopeNotPresentException extends Exception {}
protected Target(T scope) { this.scope = new WeakReference<T>(scope); }
// this is the raw callback called by the button when user clicks
// it throws an exception if the scope is null, otherwise it executes onTouch (to be overrided)
final public void onTouchRawCallback() throws ScopeNotPresentException {
if(scope.get() == null)
throw new ScopeNotPresentException();
else
onTouch(scope.get());
}
// when this subclassed method is executed, the scope is verified to be not null
protected void onTouch(T scope) { }
}
My button class raw callback does :
try {
mTarget.onTouchRawCallback();
}
catch(Target.ScopeNotPresentException e){
Log.w(LOG_TAG, "target button method was ignored because scope weak ref is null");
}
So, if scope.get() is null, the exception is triggered and onTouch()
is not called. Finally, all my Fragment add a handler to their buttons like so :
mybutton.addTarget(new MyCustomButton.Target<MyFragment>(this) {
@Override
protected void onTouch(MyFragment scope) {
scope.fragmentCustomClickHandler();
}
});
But this is of course much more verbose than mybutton.addTarget(this::mycallback);
. I saw that I couldn't use lambda for generic typed class with arguments passed to constructor.
Do you have any idea of a better implementation so I could keep using lambda short syntax while having a safe retrieval of this
, using weak references ? (For exemple, in swift, it's
addTarget({ [weak self] self?.myCallback(); })
which stops if self is null)
专注分享java语言的经验与见解,让所有开发者获益!
评论