在Android上按下后退按钮时Runnable线程会发生啥?

Posted

技术标签:

【中文标题】在Android上按下后退按钮时Runnable线程会发生啥?【英文标题】:On Android what happens to Runnable thread when back button pressed?在Android上按下后退按钮时Runnable线程会发生什么? 【发布时间】:2017-01-30 09:25:35 【问题描述】:

我有一个 Runnable(比如“MyThread”),它执行一个长任务并使用/锁定一个线程安全的单例。

我注意到,当按下后退按钮时,屏幕会立即退出活动,并且没有视觉指示 MyThread 已正确完成。

当我“重新打开”我的应用程序时,单例仍然被锁定,这也证明了这一点!!!!当然 getLockedInstance() 返回 null。

所以我想我的问题是...... 即使在执行关键任务时按下后退按钮,Android 应用程序到底会发生什么? 线程是否终止?活动的线程是否被冻结,因此所有数据都被访问和使用?我们如何确保关键任务能够完成执行?

// singleton class
public class Storage

    private int count = 0;
    private static final Storage ourInstance = new Storage();

    public static synchronized Storage getLockedInstance()
    
        if (ourInstance.count > 0)
            return null;
        ourInstance.count++;
        return ourInstance;
    

    public synchronized void UnlockInstance()
    
        if (count > 0)
            count--;
    


// runnable declaration

private Runnable MyThread = new Runnable()

    @Override
    public void run()
    
        Storage s = Storage.getLockedInstance();

        ..... do stuff .....
        [back button pressed]
        ..... this is never reached .....

        s.UnlockInstance();
    

【问题讨论】:

线程不一定会停止,但如果您的应用程序现在处于后台,则该进程可能会被终止。您是否尝试过在线程中添加日志调用?如果您绝对需要运行任务,请考虑将其放入 Service 中,它将作为与您的应用程序分开的进程运行。 请从您的标题中删除“已解决”并将您找到的解决方案作为正确答案发布。 【参考方案1】:

android 中的 Thread 类与常规 Java 编程中的 Thread 类没有什么不同。它是应用程序获得的底层 Linux 本机线程的最接近的表示。 Thread 类为任务创建执行环境,由 Runnable 表示。 Thread实现了Runnable,所以要执行的任务要么由线程自己定义,要么在创建线程时注入。

当 run 方法完成执行后,线程被终止并且它的资源可以被释放。这是线程的最终状态;不能重复使用 Thread 实例或其执行环境。

中断(例如按下返回按钮)

有时,应用程序希望在线程完成任务之前终止线程的执行。例如,如果一个线程需要很长时间来下载视频并且用户按下按钮取消下载,UI 线程会捕获按钮按下并希望终止下载线程。但是,没有办法直接终止线程。相反,线程可以被中断,这是对应该终止的线程的请求,但线程本身决定是否执行。在线程引用上调用中断:

线程中断是协同实现的:线程使自己可以被中断,其他线程发出调用来中断它。发出中断对线程的执行没有直接影响;它只是在线程上设置一个内部标志,将其标记为中断。被中断的线程必须检查标志本身以检测中断并优雅地终止。一个线程必须实现取消点,以允许其他线程中断它并让它终止。

【讨论】:

我实现了一个 getLockedInstanceWait 函数(利用 Thread.sleep 方法),而不是一个“锁定并返回”类型的函数 getLockedInstance()。现在,虽然恢复活动时会有一点延迟,但最终存储对象会解锁并且我能够重新获得访问权限!这证实了你所说的 - 当活动或任何应用程序活动被恢复......然后Runnable(MyThread)也被恢复并且能够完成执行。感谢您的帮助。 @zdanman "这证实了你所说的 - 当活动或任何应用活动恢复时......然后 Runnable (MyThread) 也会恢复"您以错误的方式得到答案(从this book 复制/粘贴)。后台线程在按下后退按钮后继续运行,直到它们完成工作或进程被操作系统杀死。如果您想阻止后台线程,请参阅this 或使用Service “中断(比如按下返回键)”你说的是什么类型的中断? @Onik ,Anders Goransson 在他的书中提到,例如“如果用户按下按钮取消下载(即与按下返回按钮相同),这是一个中断示例。此外,您提到线程一直运行直到他们完成他们的工作,这重复了答案中提到的相同事情(但是,线程无法直接终止。当 run 方法完成执行时,线程被终止并它的资源可以被释放)【参考方案2】:

(代表 OP 发布)

感谢大家(和@A.J A.J)的 cmets 和帮助。我误诊了问题,实际上是我的问题。

线程确实完成了执行,但由于它是一个漫长的过程,因此应用程序恢复到的任何活动都无法访问 Storage 对象。我的解决方案是使用 getLockedInstanceWait() 函数(见下文),而不是之前使用的“锁定并返回”类型:

public static Storage getLockedInstanceWait()

    Storage s = null;
    while ((s = Storage.getLockedInstance()) == null)
    
        try
        
            Thread.sleep(500);
        
        catch (InterruptedException e)
        
            return null;
        
    

    return s;

【讨论】:

以上是关于在Android上按下后退按钮时Runnable线程会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章

Android Fragment句柄后退按钮按下[重复]

按下后退按钮时未调用Android onUserLeaveHint()

Android:按下后退按钮时提示用户保存更改

按下后退按钮未触发

在android中按下后退按钮后如何返回相同的选项卡?

按下后退按钮/折叠搜索字段时,Android 搜索菜单项消失