【问题标题】:What happens to an Android thread after the Activity that created it is destroyed?创建它的 Activity 被销毁后,Android 线程会发生什么?
【发布时间】:2011-09-06 16:44:27
【问题描述】:

在我的 Android 应用中,主 Activity 有时会启动一个线程来从服务器加载数据。该线程修改应用程序的数据库并编辑一些重要文件。 AFAIK,看来这个线程继续执行。如果 Android 遇到内存不足的情况并决定终止整个应用程序,该线程会发生什么?是否会出现此线程可能过早死亡的情况?如果是这样,有什么方法可以让我看到线程被杀死,然后做点什么?

我问是因为这个线程修改了数据库中的重要数据,如果它突然被杀死,应用程序可能会停止正常运行。

【问题讨论】:

    标签: java android multithreading android-activity


    【解决方案1】:

    AFAIK,看来这个线程会继续执行。

    这是真的,但你无法保证线程会存活多久。

    如果 Android 遇到内存不足的情况并决定终止整个应用程序,该线程会发生什么?

    根据我的经验,这实际上是一个相当罕见的情况,但这取决于设备的可用内存和用户的行为,例如他们大量使用设备并启动多个应用程序。

    是否会出现此线程可能过早死亡的情况?

    是的

    如果是这样,有什么方法可以让我看到线程正在被杀死,然后做点什么?

    没有

    我问是因为这个线程修改了数据库中的重要数据,如果它突然被杀死,应用程序可能会停止正常运行。

    您所描述的可以归类为“关键任务”。正如其他两个答案所指出的那样,服务将是一种更强大的做事方式,因为服务是在内存不足的情况下最后被“杀死”的事情之一。使用 START_REDELIVER_INTENT 可能有助于恢复它正在做的事情。

    在任何情况下,如果您有“关键任务”操作,则需要设计代码以实现完全恢复,例如使用事务以及在发生错误时回滚的可能性。

    【讨论】:

    • 当然,您可以做一些事情。但是,一旦您允许应用程序被销毁 - 比onDestroy 更早采取行动 - 在onStop 中设置一个线程可以轮询的标志,以了解应用程序存在消失的风险。清除 onResume 中的标志。线程在尽可能短的块中完成它的工作,如果它看到那个标志,它就会结束自己。在每个块结束时,它会更新文件中的进度状态,因此可以正确重新启动。同样在 onStop 中,直到 !thread.isAlive 或 1 秒后才返回 - 循环使用测试和计数器,每次睡眠 100 毫秒,不超过 10 次。
    • 线程还需要在任何长时间延迟(例如来自服务器的响应)之后以及在执行关键操作(更新本地文件/数据库)之前检查标志。它永远不会以设置该标志的方式开始一个关键部分。只要关键部分不超过 100-200 毫秒,我认为你在实践中是安全的。 (并不是说这是任务关键型应用程序的好方法,但对我们大多数人来说已经足够了。)请注意,我的方法的本质是在您的应用程序还活着的时候完成工作 - 通过延迟@987654326 @ 最多 1 秒。在许多情况下,这就是所有需要的。
    • 更新:我关于延迟 1 秒的建议太长了,不适合 onStop。需要研究多长时间是合适的——Android 对合理时间的定义是什么。请注意,如果有任何 UI 调用在 Android 应该有点宽松,它是 onStop,因为这是应用程序确保保留他们关心的任何内容的最后机会。
    【解决方案2】:

    听起来您应该将数据库更新移至服务。一旦一个 Activity 进入后台,Android 假定它的进程可以在必要时被终止并在以后重新启动而不会产生不良影响。请参阅Application Fundamentals 了解更多信息。

    【讨论】:

      【解决方案3】:

      您应该使用服务:

      因为运行服务的进程是 排名高于一个进程 背景活动,活动 启动一个长期运行的 操作可能会很好地开始 该操作的服务,而不是 而不是简单地创建一个工人 线程——特别是如果操作 可能会比活动更持久。

      看这里:http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html#Lifecycle(我粘贴的文本的来源)

      【讨论】:

        【解决方案4】:

        我可能正在挖掘一个旧线程,但没有人提到一件重要的事情。

        每次使用数据库并修改多行时,都应使用事务来确保数据在发生任何类型的故障(例如线程终止、套接字异常等)。

            try{
                db.beginTransaction(); 
        
                //Do whatever you need to do...    
        
                db.setTransactionSuccessful();
            }catch(SQLiteException e){
                Log.e("SQLite","Error while updating rows: " + e.getMessage());
            }finally{
                db.endTransaction(); //Commit (if everything ok) or rollback (if any error occured). 
                db.close(); //Close databse;
            }
        

        【讨论】:

          猜你喜欢
          • 2016-03-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-08-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多