Android 在静态方法中调用new Runnable()是否可以防止内存泄漏?
在我的“活动”中,我希望在加载“活动”后1秒出现一个浮动操作按钮 为此,我创建了一个新的静态方法,如下所示Android 在静态方法中调用new Runnable()是否可以防止内存泄漏?,android,multithreading,memory-leaks,Android,Multithreading,Memory Leaks,在我的“活动”中,我希望在加载“活动”后1秒出现一个浮动操作按钮 为此,我创建了一个新的静态方法,如下所示 public class utility { public static void delayedShowFab(final FloatingActionButton fab) { new Handler().postDelayed(new Runnable(){ @Override public void run(
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秒后自动销毁吗?是和否。在正常操作中,引用将被清除,内存将被释放。从技术上讲,如果活动在1秒之前被终止,则存在内存泄漏。
FloatingActionButton
仍然保存对其父上下文的引用。因此,活动
将保留在内存中,直到处理程序处理消息为止,在这种情况下,fab将显示,但由于该活动已不在视图中,因此不会出现任何可见的情况
这不会对性能产生太大的影响,因为它只有一秒钟。这一秒钟的开销很小,但没有什么意义。真正的问题是,如果你把时间延长一分钟
public class utility {
public static void delayedShowFab(final FloatingActionButton fab)
{
new Handler().postDelayed(new Runnable(){
@Override
public void run() {
fab.show();
}
}, 1000 * 60);
}
}
现在,假设用户刚刚决定在那一分钟内将手机旋转一百次(可能他正在慢跑,屏幕打开了,谁知道呢?)
每次屏幕旋转时,都会使用新的晶圆厂创建一个新的活动。您立即发布到主线程以等待另一分钟。在运行此消息之前,创建的每个活动都将存在。这意味着该活动中包含的所有资源也将在此期间存在
要解决这个问题,有几个选择
选项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);
}
}
}
}
然后,在活动的ondestory
方法中,只需对返回的对象调用cancel
选项2:使用弱引用
用于保留对对象的引用,而不将其包含在引用计数中。这样,当对该对象的所有引用都消失时,它将消失
因此,在本例中,您将持有对FloatingActionButon的弱引用
并且只有当它仍然存在时才调用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);
}
}
公共类实用程序{
公共静态无效延迟显示fab(最终浮动操作按钮fab)
{
最终WeakReference ref=新WeakReference(fab);
new Handler().postDelayed(new Runnable()){
@凌驾
公开募捐{
FloatingActionButton fab=ref.get();
//你总是要检查,因为它可能会消失。
如果(fab!=null){
fab.show();
}
}
}, 1000 * 60);
}
}
在此解决方案中,Runnable
和WeakReference
将在消息持续期间保留在内存中,但开销明显小于完整活动 是和否。在正常操作中,将清除引用并释放内存。从技术上讲,如果活动在1秒之前被终止,则存在内存泄漏。FloatingActionButton
仍然保存对其父上下文的引用。因此,活动
将保留在内存中,直到处理程序处理消息为止,在这种情况下,fab将显示,但由于该活动已不在视图中,因此不会出现任何可见的情况
这不会对性能产生太大的影响,因为它只有一秒钟。这一秒钟的开销很小,但没有什么意义。真正的问题是,如果你把时间延长一分钟
public class utility {
public static void delayedShowFab(final FloatingActionButton fab)
{
new Handler().postDelayed(new Runnable(){
@Override
public void run() {
fab.show();
}
}, 1000 * 60);
}
}
现在,假设用户刚刚决定在那一分钟内将手机旋转一百次(可能他正在慢跑,屏幕打开了,谁知道呢?)
每次屏幕旋转时,都会使用新的晶圆厂创建一个新的活动。您立即发布到主线程以等待另一分钟。在运行此消息之前,创建的每个活动都将存在。这意味着该活动中包含的所有资源也将在此期间存在
要解决这个问题,有几个选择
选项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);
}
}
}
}
然后,在活动的ondestory
方法中,只需对返回的对象调用cancel
选项2:使用弱引用
用于保留对对象的引用,而不将其包含在引用计数中。这样,当对该对象的所有引用都消失时,它将消失
因此,在本例中,您将持有对FloatingActionButon的弱引用
并且只有当它仍然存在时才调用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);
}
}
公共类实用程序{
公共静态无效延迟显示fab(最终浮动操作按钮fab)
{
最终WeakReference ref=新WeakReference(fab);
new Handler().postDelayed(new Runnable()){
@凌驾
公开募捐{
FloatingActionButton fab=ref.get();
//你总是要检查,因为它可能会消失。
如果(fab!=null){
fab.show();
}
}
}, 1000 * 60);
}
}
在此解决方案中,Runnable
和WeakReference
将在消息持续期间保留在内存中,但开销明显小于完整活动 我已经放弃了这样的设计——它们似乎从来都不适合我。未知崩溃由于其他进程占用CPU,一秒变成五秒。今天,我要做的只是构建UI的最后一步,使按钮可见,并继续制作一个伟大的应用程序。我已经放弃了设计