Android中Finish和OnBackPressed、OnDestroy的区别_finish onbackpressed_luo_boke的博客-程序员秘密

技术标签: OnDestroy  Android基础  源码分析  Activity的几种关闭方式  Finish和OnBackPressed  Android  

开发的过程中,常常见到finish()和onBackPressed()以及ondestory好像都能关掉Activity。自己抽空总结一下,首先看源码,源码基于'androidx.appcompat:appcompat:1.1.0'来分析。

1.Finish

android.app.Activity中源码:
    @Override
    public void finish() {
        //关闭activity但不关闭栈
        finish(DONT_FINISH_TASK_WITH_ACTIVITY);
    }

    public void finishAndRemoveTask() {
        //如果当前activity是处于栈底,则关闭activity的同时关闭栈
        finish(FINISH_TASK_WITH_ROOT_ACTIVITY);
    }


    /**
     * 完成当前活动并指定是否删除与此活动关联的任务。
     */
    private void finish(int finishTask) {
        if (mParent == null) {
            int resultCode;
            Intent resultData;
            synchronized (this) {
                resultCode = mResultCode;
                resultData = mResultData;
            }
            if (false) Log.v(TAG, "Finishing self: token=" + mToken);
            try {
                if (resultData != null) {
                    // 准备此{@link Intent}以退出应用程序进程。
                    resultData.prepareToLeaveProcess(this);
                }
                // 1、猜测更具finish的类别finishTask进行关闭
                // 退回上一个Activity,并且会将resultCode, resultData返回。如果启动的是startActivityForResult将会在onActivityResult响应
                if (ActivityManager.getService().finishActivity(mToken, resultCode, resultData, finishTask)) {
                    mFinished = true;
                }
            } catch (RemoteException e) {
                // Empty
            }
        } else {//如果有嵌套的父级Activity,则在父级activity关闭,此时childActivity会被自动销毁。
            mParent.finishFromChild(this);
        }

        //如果Intent中带有要保存UI信息,则应该保存mInten中的信息
        if (mIntent != null && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)) {
            getAutofillManager().onPendingSaveUi(AutofillManager.PENDING_UI_OPERATION_RESTORE, mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN));
        }
    }

2.OnDestroy

  androidx.appcompat.app.AppCompatActivity中的源码
  @Override
    protected void onDestroy() {
        super.onDestroy();
        getDelegate().onDestroy();
    }
    
   
    androidx.fragment.app.FragmentActivity中的源码
    @Override
    protected void onDestroy() {
        super.onDestroy();
        //关闭可能包含的Fragment
        mFragments.dispatchDestroy();
        //让Lifecycle处于destory状态
        mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
    }  

   android.app.Activity中的源码
    /**
     * 1、在销毁活动之前执行任何最后的清理。可以是人为调用了finish,或者系统内存紧张调用了。
     * 2、不能在destory中保存数据,因为系统将简单地杀死活动的托管过程,即可能关闭程序ondestory不一定被调用了
     * 3、子类必须调用super.onDestory
     */
    @CallSuper
    protected void onDestroy() {
        if (DEBUG_LIFECYCLE) Slog.v(TAG, "onDestroy " + this);
        mCalled = true;

        /**
         * 关闭当前Activity管理的所有dialog,所以diaolog 不应该使用applicationContext
         */
        if (mManagedDialogs != null) {
            final int numDialogs = mManagedDialogs.size();
            for (int i = 0; i < numDialogs; i++) {
                final ManagedDialog md = mManagedDialogs.valueAt(i);
                if (md.mDialog.isShowing()) {
                    md.mDialog.dismiss();
                }
            }
            mManagedDialogs = null;
        }

        // 关闭任何Cursors,所以cursor不应该用ApplicationContext初始化
        // 现在的版本比以前的低版本对内存泄漏的检测和解决更加强大了
        synchronized (mManagedCursors) {
            int numCursors = mManagedCursors.size();
            for (int i = 0; i < numCursors; i++) {
                ManagedCursor c = mManagedCursors.get(i);
                if (c != null) {
                    c.mCursor.close();
                }
            }
            mManagedCursors.clear();
        }

        //关闭任何 searchDialog
        if (mSearchManager != null) {
            mSearchManager.stopSearch();
        }

        //关闭ActionBar
        if (mActionBar != null) {
            mActionBar.onDestroy();
        }

        //ActivityLifecycleCallbacks 取消生命周期回调监听
        getApplication().dispatchActivityDestroyed(this);
    }

3.OnDestory

 androidx.activity.ComponentActivity中的源码  
 public void onBackPressed() {
        mOnBackPressedDispatcher.onBackPressed();
 }

 androidx.activity.OnBackPressedDispatcher中的源码
    /**
     * 1、只有最后按得back返回键,才能将OnBackPressedCallback 设置为isEnabled=true
     * 2、旧版的OnbackPressed好分析一些
     * 3、随着版本的更新,软件内部的代码结构和构造是不断变化的
     */
    @MainThread
    public void onBackPressed() {
        Iterator<OnBackPressedCallback> iterator =
                mOnBackPressedCallbacks.descendingIterator();
        while (iterator.hasNext()) {
            OnBackPressedCallback callback = iterator.next();
            if (callback.isEnabled()) {
                callback.handleOnBackPressed();
                return;
            }
        }
        if (mFallbackOnBackPressed != null) {
            mFallbackOnBackPressed.run();
        }
    }

总结:

1、调用onBackPressed()方法不一定就能结束Activity。

2、调用onBackPressed()方法结束Activity,其调用的终究还是finish()方法。

3、finish()方法最后调用了Ondestory。

4、Android系统内存紧张时,可能会关闭软件进程,此时Activity的该方法不一定必然被调用。

 
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/luo_boke/article/details/103975902

智能推荐

8小时快速入门,golang安装学习,有语言基础的快来学习_黄昏单车的博客-程序员秘密

安装golang(Linux环境)# 下载linux源码包中文官网地址https://studygolang.com/dl# 下载命令直接下载wget https://studygolang.com/dl/golang/go1.17.2.linux-amd64.tar.gz# 解压到指定目录tar -zxf go1.17.2.linux-amd64.tar.gz -C /usr/local# 配置go的相关路径,在末尾加入以下内容vim ~/.bashrc# 设置go语言路径exp..

LeetCode -- 695. 岛屿的最大面积_leetcode 移动一个格子 最大面积_Yumi Mammy的博客-程序员秘密

来自图解面试算法。这道题的主要思路是深度优先搜索。每次走到一个是1的格子,就搜索整个岛屿,并计算当前岛屿的面积。最后返回岛屿面积的最大值。网格可以看成是一个无向图的结构,每个格子和它上下左右四个格子相邻。如果四个相邻的格子坐标合法,就可以继续搜索。在深度优先搜索的时候要注意避免重复遍历。我们可以把已经遍历过的陆地改成2,这样遇到2我们就知道已经遍历过这个格子了,不进行重复遍历。class Solution { public int maxAreaOfIsland(int[][] gri...

【知了堂学习笔记】_Ajax基础知识_TANGLHUI的博客-程序员秘密

请关注“知了堂学习社区”,地址:http://www.zhiliaotang.com/portal.php1.Ajax作用ajax是什么 传统web应用采用同步交互方式实现数据呈现,当服务器处理请求时,客户端必须要等待ajax建立起了浏览器客户端与服务器之间的桥梁,可以消除网络交互过程中对的处理-等待-处理的缺陷ajax全称:Asynchronous JavaScript and XML 异

eeprom stm8l 擦除 读写_STM8S_库函数_片上EEPROM读写操作_weixin_39748445的博客-程序员秘密

大家好,我是单片机爱好者-MCU起航。这里说下使用库函数方式控制STM8S103F3P6实现片上EEPROM读写操作。很多人接触EEPROM,都是从24C01或者24C02开始。因为早期的单片机资源比较匮乏,所以需要外接这些东西。但随着单片机的片上资源越来越丰富,在某些情况下,这些外接的EEPROM其实是可以省掉的。相当一部分的单片机内部集成了一部分EEPROM,还有的单片机,内部虽然没有EEPR...

Linux 校准日期_安静平和的博客-程序员秘密

1、更新时间    $ ntpdate time-a.nist.gov2、查看日志 date    Wed Dec  3 00:20:06 EST 2008       这个时间是不对的,明显时区错误“EST”,这时你需要这么做:    $ cp /usr/share/zoneinfo/Asia/shanghai /etc/localtime    这就是把该时区文件覆

STM32?I2C-EEPROM_linzhihan7410的博客-程序员秘密

I2C????: I2C(inter-integrated Circuit)????Phiilps?????,???????,??????,?????(??USART,CAN???????),??????????????????(IC)?????. (??I2C????,?????I2C?????????) ???: 1,????????,?????????(SDA)

随便推点

模拟赛心得体会&COCI2014/2015CONTEST #1_SaltyFishWei的博客-程序员秘密

又一次挂了,简直无语。一二题A了,然后就卡在第三题。第三题思路我很快就想出来了,然后就卡在实现上面了,我居然用了高精度,本来模乘法也可以过得;奇怪的是我的前几个点都过了,后面几个全部暴栈,至今没有找出原因,可能是求答案的时候写丑了之后就一直想第四题,一道只有几百B的神代码- -,几乎用完的所有的时间,结果还是没有想出来!然后第五题我想出来dp,自认为可以过几个点,结果没有时间调试了,然

vue-router 路由跳转传参刷新页面后参数丢失问题_route.params传参丢失_榴莲豆包的博客-程序员秘密

常见场景:点击列表详情,跳转到详情内页,传递id参数获取详情数据。我们先来看看路由跳转的几种方式:1、通过params方式传参通过$route.push的path携带参数方式(路由配置中指定参数)// 路由配置{ path: '/detail/:id', //若id后面加?代表这个参数是可选的,即使不传id也不会导致页面无法访问 name: 'detail', component: Detail }// 列表中跳转this.$router.push({

bzoj 1270: [BeijingWc2008]雷涛的小猫 dp_everlasting__的博客-程序员秘密

→题目链接←一看到题就可以想到是动态规划首先不作任何优化的dp时间复杂度显然是n^3的dp[i][j]表示第i棵树,高度为j时最多可以吃到多少个柿子num[i][j]表示第i棵树,高度为j的位置上有几个柿子显然dp[i][j]=max(dp[i][j+1]+num[i][j] , dp[1~n][j+delta]+num[i][j])但是n^3是过不了的我们发现

基于安卓开发的QQ登陆页面,实现登陆注册内容_android实现qq注册_int inunk的博客-程序员秘密

基于安卓开发的QQ登陆页面,实现登陆注册内容(一)QQ登陆注册首先对于QQ登陆注册而言,先控制好布局,和对控件的使用;页面效果如下:部分代码:&lt;TextView android:layout_width="match_parent" android:layout_height="67dp" android:layout_marginTop="50dp"...

Android Studio怎么打包成APK_android studio文件打包成app。_生活热爱就好的博客-程序员秘密

1.确定软件版本将项目切换到Project,打开app目录下的build.gradle文件versionCode是app的大版本好,为数值类型,默认为1,改成2versionName是app的具体版本号,为际符串类型,默认为1.0,改成2.02.指定生成的APK文件名还是在刚刚的bulid.gradle文件中修改,默认生成release版apk名为app-release.apk在android内部修改自己的apk名3.生成自己密钥签名的realease版apk直接点Build APK(s

设计模式_外观模式_外观模式 设计模式_帝江VII的博客-程序员秘密

外观模式外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。#ifndef _FACADE_H_#define _FACADE_H_#include//子系统1class subSystemOne{public: void subMet

推荐文章

热门文章

相关标签