在我的Activity中,我想在活动加载后1秒钟出现一个浮动的Action按钮。
为此,我创建了一个像这样的新静态方法。
public class utility {
public static void delayedShowFab(final FloatingActionButton fab)
{
new Handler().postDelayed(new Runnable(){
@Override
public void run() {
fab.show();
}
}, 1000);
}
}
我正在调用这样的方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
utility.delayedShowFab(fab);
}
我的代码是否可以免受内存泄漏的影响?新的Runnable和新的Handler对象会在1秒后自动销毁吗?
答案 0 :(得分:2)
是和否。在正常操作中,将清除引用并释放内存。从技术上讲,如果Activity在一秒钟之前被杀死,就会发生内存泄漏。 FloatingActionButton
仍然保留对其父Context
的引用。所以Activity
将保留在内存中,直到Handler处理消息,在这种情况下fab将显示,但由于Activity不再可见,所以不会发生任何事情。
这不会对性能产生巨大影响,因为它只有一秒钟。这一秒只有一些小的开销,但没有什么重要的。 真正的问题是,如果你延长那个时间让我们说,1分钟。
public class utility {
public static void delayedShowFab(final FloatingActionButton fab)
{
new Handler().postDelayed(new Runnable(){
@Override
public void run() {
fab.show();
}
}, 1000 * 60);
}
}
现在,让我们说用户刚刚决定在那一分钟内将手机旋转一百次(也许他正在慢跑并且屏幕已开启。谁知道?)。
每次屏幕旋转时,都会使用新的FAB创建一个新的活动。您立即发布到主线程等待一分钟。在运行此消息之前,创建的每个活动都将存在。这意味着该活动中包含的所有资源也将在该持续时间内存在。
为了解决这个问题,有一些选择。
选项1:取消操作。
保持API完好无损。您可以返回取消操作的方法。与此类似:
public class utility {
public interface Cancelable {
void cancel();
}
public static void delayedShowFab(final FloatingActionButton fab) {
final Handler handler = new Handler();
final Runnable runnable = new Runnable(){
@Override
public void run() {
fab.show();
}
};
handler.postDelayed(runnable, 1000);
return new Cancelable() {
public void cancel() {
handler.removeCallbacks(runnable);
}
}
}
}
然后,在Activity的onDestroy
方法中,只需在返回的对象上调用cancel
。
选项2:使用弱引用
WeakReferences用于保存对象的引用,而不将其包含在引用计数中。这样,当对该对象的所有引用都消失时,它将消失。
因此,在这种情况下,您将对FloatingActionButon持有WeakReference
如果它仍然存在,则只调用show
。
public class utility {
public static void delayedShowFab(final FloatingActionButton fab)
{
final WeakReference<FloatingActionButton> ref = new WeakReference<>(fab);
new Handler().postDelayed(new Runnable(){
@Override
public void run() {
FloatingActionButton fab = ref.get();
// You always have to check because it may disappear.
if(fab != null) {
fab.show();
}
}
}, 1000 * 60);
}
}
在此解决方案中,Runnable
和WeakReference
将在邮件持续时间内保留在内存中,但开销明显低于完整活动。