本网站(662p.com)打包出售,且带程序代码数据,662p.com域名,程序内核采用TP框架开发,需要联系扣扣:2360248666 /wx:lianweikj
精品域名一口价出售:1y1m.com(350元) ,6b7b.com(400元) , 5k5j.com(380元) , yayj.com(1800元), jiongzhun.com(1000元) , niuzen.com(2800元) , zennei.com(5000元)
需要联系扣扣:2360248666 /wx:lianweikj
Android进阶之深入理解Activity生命周期源码
飘飘悠悠 · 439浏览 · 发布于2021-08-24 +关注

Activity是一个很重要、很复杂的组件,他的启动不像我们平时直接new一个对象就完事了,他需要经历一系列的初始化。


前言

Activity是一个很重要、很复杂的组件,他的启动不像我们平时直接new一个对象就完事了,他需要经历一系列的初始化。例如"刚创建状态",“后台状态”,“可见状态”等等;

当我们在界面之间进行切换的时候,activity也会在多种状态之间进行切换,可见或者不可见状态、前台或者后台状态。当Activity在不同的状态之间切换时,会回调不同的生命周期方法;

今天我们就来总结下Activity生命周期;

一、生命周期

Activity个状态生命周期流程图

由上图可知:

1.Starting -> Running,执行的生命周期顺序 onCreate()->onstart()->onResume(),

此activity所处于任务栈的top中,可以与用户进行交互。

2.Running -> Paused ,执行Activity生命周期中的onPause(),

该Activity已失去了焦点但仍然是可见的状态(包括部分可见)。就比如弹出DialogActivity

3.Paused -> Running,执行Activity生命周期中的onResume(),

此情况用户操作[home键],然后重新回到当前activity界面,还有就是关闭DialogActivity

1.Activity1 跳转至 Activity2 执行的生命周期:

Activity1:onPause 
Activity2:onCreate 
Activity2:onStart 
Activity2:onResume 
Activity1:onStop

    2.Activity2回到Activity1 执行的生命周期:

    Activity2:onPause 
    Activity1:onRestart 
    Activity1:onStart 
    Activity1:onResume 
    Activity2:onStop 
    Activity2:onDestory

      3. LifeCycleActivity弹出DialogActivity 执行的生命周期:

      LifeCycleActivity:onPause 
      DialogActivity:onCreate 
      DialogActivity:onStart 
      DialogActivity:onResume 
      值得注意的是:这里 LifeCycleActivity不会进入onStop,因为弹出DialogActivity时LifeCycleActivity还处于可见

        4.DialogActivity返回键到LifeCycleActivity执行的生命周期:

        DialogActivity:onPause 
        LifeCycleActivity:onResume 
        DialogActivity:onStop 
        DialogActivity:onDestroy

          5.LifeCycleActivity旋转屏幕执行的生命周期:

          LifeCycleActivity:onPause 
          LifeCycleActivity:onStop 
          LifeCycleActivity:onDestroy 
          LifeCycleActivity:onCreate 
          LifeCycleActivity:onStart 
          LifeCycleActivity:onResume 
          这里相当于重新创建了Activity

            6.Activity横竖屏切换状态保存:

            当前ViewPager有三个Fragment,在竖屏时选择的Fragment为第二个,如何在切换横屏后选中第二个Fragment并且Fragment保持之前的状态?

            由于onCreate可以拿到保持状态的Bundle,而每次onPause以及onStop都会回调onSaveInstanceState(Bundle outState)方法;

            所以可在该方法就行保存状态,大体代码如下:

            @Override 
            protected void onCreate(Bundle savedInstanceState) { 
                    super.onCreate(savedInstanceState); 
                    setContentView(R.layout.activity_main); 
                    // 初始化主页fragment 
                    if (savedInstanceState != null) { 
                        //系统回收后重新进入当前页面恢复数据 
                        resumeFragment(getSupportFragmentManager(), savedInstanceState); 
                        resumeIndex(savedInstanceState); 
                        showSelectFragmentOnly(getSupportFragmentManager()); 
                        mTabLayout.setCurrentItem(mIndex); 
                    } else { 
                        //正常初始化 
                        mTabLayout.setCurrentItem(0); 
                        showFragment(getSupportFragmentManager(), 0); 
                        mIndex=0; 
                    } 
                } 
               private void resumeFragment(FragmentManager fragmentManager, Bundle savedInstanceState) { 
                    Fragment[] fragments = new Fragment[fragmentTab.length]; 
                    for (int i = 0; i < fragments.length; i++) { 
                        fragments[i] = fragmentManager.getFragment(savedInstanceState, fragmentTab[i].getSimpleName()); 
                    } 
                    mFragments = fragments; 
                } 
                private void resumeIndex(Bundle savedInstanceState) { 
                    mIndex = savedInstanceState.getInt(CURRENT_INDEX, 0); 
                } 
              @Override 
                protected void onSaveInstanceState(Bundle outState) { 
                    super.onSaveInstanceState(outState); 
                    for (Fragment fragment : mFragments) { 
                        if (fragment != null) { 
                            getSupportFragmentManager().putFragment(outState, fragment.getClass().getName(), fragment); 
                        } 
                    } 
                    outState.putInt(CURRENT_INDEX, mIndex); 
                }

              下图概括了android生命周期的各个环节,描述了activity从生成到销毁的过程

              • 创建:onCreate():

              • |---可用于初始化工作,如setContentView界面资源、初始化数据

              • 启动:onStart():

              • |---可见但无法交互

              • 恢复:onResume():

              • |---恢复播放动画、音乐、视频等

              • 暂停:onPause():

              • |---可做数据存储、停止动画、音乐、视频等

              • 停止:onStop():

              • |---此时Activity不可见,可做视情况做些重量级回收工作,避免被Killed

              • 销毁:onDestroy():

              • |---回收工作、资源释放

              • 重现:onRestart():

              • |---可做一些恢复工作

              二、Activity基本结构

              • 一个应用程序通常由多个Activity组成,那么在应用程序中肯定需要一个容器来盛放这些Activity,必要时通过该容器找到对应的Activity,并进行相关操作。上一篇文章已经讲过一个应用程序对应一个ActivityThread,所以自然而然地该容器是ActivityThread在负责维护,这个容器叫做mActivities,是一个数组,里面的每一项叫做ActivityRecord,一个ActivityRecord对应一个Activity。

              • 以上仅仅是应用级别的管理容器,但是很多场景下,系统需要找到某一个特定的Activity,并下发相关数据比如事件分发。所以还必须在系统层面再维护一个容器,这个容器存放在Activity Manager Service,对应的容器叫做mHistory,对应的每一项叫做HistroyRecord。

              • 每个Activity必须依靠在进程中,每个进程对应一个AMS中的ProcessRecord,通过这个ProcessRecord可以找到对应的应用的所有Activity,同时还提供了与Activity联系的接口IActivityThread。

              • 所以整个Activity的管理框架如下图所示:

              三.生命周期源码详解

              在Launch Activity时,AMS将对应的HistoryRecord作为token传递到客服端和客服端的Activity建立联系。在AMS中Activity状态变化时,将通过该联系找到客服端的Activity,从而将消息或者动作传递应用程序面对的接口:xxxActivity。整个Activity的启动过程大致可以分为以下几个步骤:

              发起startActivity(intent)请求

              AMS接收到请求后,创建一个HistroyRecord对象,并将该对象放到mHistory数组中

              调用app.thread.scheduleLaunchActivity()

              AMS创建ActivityRecord对象,将创建的Activity放入到ActivityRecord,再将其放入到mActivities

              发起Activity的onCreate()方法

              1、Activty是如何创建?ActivityThread 便是这关键

              public final class ActivityThread { 
                 Instrumentation mInstrumentation; 
                  ...... 
                  final ApplicationThread mAppThread = new ApplicationThread(); 
                 // Looper类创建 
                  final Looper mLooper = Looper.myLooper(); 
                 // H是继承Handler类 在AcivityThread创建时就创建了 
                  final H mH = new H(); 
                 ...... 
              }

                H类源码如下:

                private class H extends Handler { 
                ........ 
                 public void handleMessage(Message msg) { 
                            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what)); 
                            switch (msg.what) { 
                                case LAUNCH_ACTIVITY: { 
                                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart"); 
                                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj; 
                                    r.packageInfo = getPackageInfoNoCheck( 
                                            r.activityInfo.applicationInfo, r.compatInfo); 
                                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY"); 
                                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 
                                } break; 
                                case RELAUNCH_ACTIVITY: { 
                                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart"); 
                                    ActivityClientRecord r = (ActivityClientRecord)msg.obj; 
                                    handleRelaunchActivity(r); 
                                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 
                                } break; 
                                case PAUSE_ACTIVITY: { 
                                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause"); 
                                    SomeArgs args = (SomeArgs) msg.obj; 
                                    handlePauseActivity((IBinder) args.arg1, false, 
                                            (args.argi1 & USER_LEAVING) != 0, args.argi2, 
                                            (args.argi1 & DONT_REPORT) != 0, args.argi3); 
                                    maybeSnapshot(); 
                                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 
                                } break; 
                                case PAUSE_ACTIVITY_FINISHING: { 
                                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause"); 
                                    SomeArgs args = (SomeArgs) msg.obj; 
                                    handlePauseActivity((IBinder) args.arg1, true, (args.argi1 & USER_LEAVING) != 0, 
                                            args.argi2, (args.argi1 & DONT_REPORT) != 0, args.argi3); 
                                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 
                                } break; 
                                case STOP_ACTIVITY_SHOW: { 
                                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop"); 
                                    SomeArgs args = (SomeArgs) msg.obj; 
                                    handleStopActivity((IBinder) args.arg1, true, args.argi2, args.argi3); 
                                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 
                                } break; 
                                case STOP_ACTIVITY_HIDE: { 
                                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop"); 
                                    SomeArgs args = (SomeArgs) msg.obj; 
                                    handleStopActivity((IBinder) args.arg1, false, args.argi2, args.argi3); 
                                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 
                                } break; 
                                case SHOW_WINDOW: 
                                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityShowWindow"); 
                                    handleWindowVisibility((IBinder)msg.obj, true); 
                                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 
                                    break; 
                                case HIDE_WINDOW: 
                                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityHideWindow"); 
                                    handleWindowVisibility((IBinder)msg.obj, false); 
                                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 
                                    break; 
                                case RESUME_ACTIVITY: 
                                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume"); 
                                    SomeArgs args = (SomeArgs) msg.obj; 
                                    handleResumeActivity((IBinder) args.arg1, true, args.argi1 != 0, true, 
                                            args.argi3, "RESUME_ACTIVITY"); 
                                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 
                                    break; 
                                case SEND_RESULT: 
                                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDeliverResult"); 
                                    handleSendResult((ResultData)msg.obj); 
                                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 
                                    break; 
                                case DESTROY_ACTIVITY: 
                                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy"); 
                                    handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0, 
                                            msg.arg2, false); 
                                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 
                                    break; 
                ......... 
                        } 
                }

                  那么H类handleMessage是怎么被调用的呢?其实是通过ApplicationThread的scheduleLaunchActivity来完成的,这里ApplicationThread是ActivtyThread的内部类

                  ApplicationThread部分源码如下:


                  private class ApplicationThread extends IApplicationThread.Stub { 
                          ........省略...... 
                          public final void schedulePauseActivity(IBinder token, boolean finished, 
                                  boolean userLeaving, int configChanges, boolean dontReport) { 
                              int seq = getLifecycleSeq(); 
                              if (DEBUG_ORDER) Slog.d(TAG, "pauseActivity " + ActivityThread.this 
                                      + " operation received seq: " + seq); 
                              sendMessage( 
                                      finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY, 
                                      token, 
                                      (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0), 
                                      configChanges, 
                                      seq); 
                          } 
                          public final void scheduleStopActivity(IBinder token, boolean showWindow, 
                                  int configChanges) { 
                              int seq = getLifecycleSeq(); 
                              if (DEBUG_ORDER) Slog.d(TAG, "stopActivity " + ActivityThread.this 
                                      + " operation received seq: " + seq); 
                              sendMessage( 
                                               
                                  
                                          
                  					
                                  
                                  

                  相关推荐

                  android下vulkan与opengles纹理互通

                  talkchan · 1174浏览 · 2020-11-23 10:37:39
                  Android 使用RecyclerView实现轮播图

                  奔跑的男人 · 2173浏览 · 2019-05-09 17:11:13
                  微软发布新命令行工具 Windows Terminal

                  吴振华 · 867浏览 · 2019-05-09 17:15:04
                  Facebook 停止屏蔽部分区块链广告

                  · 753浏览 · 2019-05-09 17:20:08
                  加载中

                  0评论

                  评论
                  分类专栏
                  小鸟云服务器
                  扫码进入手机网页