前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[置顶] Activity 不只有跳转。功能篇(一)

[置顶] Activity 不只有跳转。功能篇(一)

作者头像
cMusketeer
发布2022-03-11 21:10:55
1.1K0
发布2022-03-11 21:10:55
举报
文章被收录于专栏:Android机器圈

Activity生命周期

1:activity四种启动方式

standard,SingleTask,SingleTop,SingleInstance

standard:是系统默认的,每次启动该activity都会创建一个实例放在返回栈中,并且置于栈顶。

SingleTop:在每次启动活动的时候如果发现栈的栈顶已经有该活动了,那么就直接使用它,不会再创建新的活动实例。如果启动的时候没有在栈顶,那么还是会创建一个新的实例,比如说A->B ,返回栈存放过程是创建A,创建B,然后B->A(并非通过back回到A),创建A实例,因为此时返回栈中栈顶是B,所以会创建A实例。

SingleTask:整个返回栈中只有一个实例。每次启动的时候,就会在返回栈中检查是否有实例,如果有实例但不在栈顶,那么就会让栈顶出栈,它称为栈顶。例子:A->B,创建A实例,创建B实例,从B->A,此时返回栈中有A实例,就会让B实例出栈,此时栈中只有A的实例,所以点击Back后就会退出程序。(只要是在A上的实例全部出栈,如ABCD,需要用到B,此时栈中AB,CD出栈)

SingleInstance:对于设置该模式的活动(Activity),会创建一个实例保存在新的返回栈中,这是因为可供其他的程序调用这个活动,达到了共享这个实例,在单个程序中如:A->B(模式SingleInstance)->C,创建A实例,创建B实例(新返回栈中),创建C实例,当点击back键时,会C弹出栈,显示A,再次点击back键,A弹出栈,显示B。原因是A和C在一个返回栈中,而B在一个新的返回栈中。

2:Activity正确使用

  在实际开发中,页面很多,activity很多,所以,想要通过运行程序来判断当前所看的页面是对应哪一个activity就要创建一个父类activity,这样的话,让他们都来继承这个父类,在父类中通过OnCreate方法来执行一些公用的代码和Log日志即可。主要BaseActivity不需要在清单中注册。

所有继承该父类的activity都要调用一个父类的onCreate方法。

代码语言:javascript
复制
public class BaseActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e("BaseActivity",getClass().getSimpleName());
    }
}

3:Activity随时随地都可以退出

  一个程序中有退出登录,这个时候就要保所有的activity,然后可以销毁所有的activity并且之后跳转到登录页面,如果想要退出到桌面,也可以加入杀死进程的代码,防止该程序进程在后台一直运行。

杀死进程代码

代码语言:javascript
复制
android.os.Process.killProcess(Process.myPid());//获取id,杀死当前id,并杀死当前进程,不可杀死其他程序进程

Activity管理类

代码语言:javascript
复制
public class ActivityCollector {
    public static List<Activity> listActivity = new ArrayList<>();
    /**
     * 添加活动
     * */
    public static void addActivity(Activity activity){
        listActivity.add(activity);
    }
    /*删除活动*/
    public static void removeActivity(Activity activity){
        listActivity.remove(activity);
    }
    /*销毁所有活动*/
    public static void finishAllActivity(){
        for (Activity activity:listActivity) {
            if(!activity.isFinishing()){
                activity.finish();
            }
        }
    }
}

4:启动Activity最佳写法

  问题:假设两个Activity,FirstActivity和SecondActivity,第二个活动不是你写的,但是你需要跳转到该页面,同时需要传一些参数,此时,你可以问你同事需要传什么参数,或者自己去看需要什么参数,这样太麻烦。这时就需要优化代码,你同事可以在第二个界面就留一个方法入口,把需要的参数都列出来,你只需要用类名.方法名即可

该方法写在第二个活动里,也就是需要跳转到的页面。

代码语言:javascript
复制
/*启动最佳写法*/
public static void actionStart(Context context,String param1,String param2){
    Intent intent  = new Intent(context,MainActivity2.class);
    intent.putExtra("param1",param1);
    intent.putExtra("param2",param2);
    context.startActivity(intent);
}

在MAinActivity1里调用。

代码语言:javascript
复制
MainActivity2.actionStart(this,"ceshi1","ceshi2");

5:生命周期以外的方法

  • onSaveInstanceState()
  • onRestoreInstanceState()

onSaveInstanceState()和onRestoreInstanceState()使用详解 https://www.jianshu.com/p/27181e2e32d2

注意

1、如果是用户自动按下返回键,或程序调用finish()退出程序,是不会触发onSaveInstanceState()和onRestoreInstanceState()的。 2、每次用户旋转屏幕时,您的Activity将被破坏并重新创建。当屏幕改变方向时,系统会破坏并重新创建前台Activity,因为屏幕配置已更改,您的Activity可能需要加载替代资源(例如布局)。即会执行onSaveInstanceState()和onRestoreInstanceState()的。

  • 1.配置改变导致Activity被杀死,横屏变竖屏:在onStop之前会调用onSaveInstanceState()保存数据在重建Activity之后,会在onStart()之后调用onRestoreInstanceState(),并把保存下来的Bundle传给onCreate()和它会默认重建Activity当前的视图,我们可以在onCreate()中,回复自己的数据。
  • 2.内存不足杀掉Activity,优先级分别是:前台可见,可见非前台,后台。

在stop()之前系统会调用onSaveInstanceState()方法,以便您的Activity可以使用一组键值对来保存状态信息。此方法的默认实现保存有关Activity视图层次结构状态的信息,例如EditText小部件中的文本或ListView的滚动位置。

代码语言:javascript
复制
static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // 保存用户自定义的状态
    savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
    savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
    
    // 调用父类交给系统处理,这样系统能保存视图层次结构状态
    super.onSaveInstanceState(savedInstanceState);
}
恢复您的Activity状态

  当您的Activity在之前被破坏后重新创建时,您可以从Bundle系统通过您的Activity中恢复您的保存状态。这两个方法onCreate()和onRestoreInstanceState()回调方法都会收到Bundle包含实例状态信息的相同方法。因为onCreate()调用该方法是系统正在创建一个新的Activity实例或重新创建一个以前的实例,所以您必须Bundle在尝试读取之前检查该状态是否为空。如果它为空,那么系统正在创建一个Activity的新实例,而不是恢复之前被销毁的实例。

例如,下面是如何恢复一些状态数据onCreate():

代码语言:javascript
复制
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); // 记得总是调用父类
   
    // 检查是否正在重新创建一个以前销毁的实例
    if (savedInstanceState != null) {
        // 从已保存状态恢复成员的值
        mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
        mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
    } else {
        // 可能初始化一个新实例的默认值的成员
    }
    ...
}

onCreate()您可以选择执行onRestoreInstanceState(),而不是在系统调用onStart()方法之后恢复状态。系统onRestoreInstanceState()只有在存在保存状态的情况下才会恢复,因此您不需要检查是否Bundle为空:

代码语言:javascript
复制
public void onRestoreInstanceState(Bundle savedInstanceState) {
    // 总是调用超类,以便它可以恢复视图层次超级
    super.onRestoreInstanceState(savedInstanceState);
   
    // 从已保存的实例中恢复状态成员
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
    mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}

6:onNewIntent()方法

该方法和启动模式紧密相关 前提:ActivityA已经启动过,处于当前应用的Activity任务栈中;

当ActivityA的LaunchMode为Standard时:

由于每次启动ActivityA都是启动新的实例,和原来启动的没关系,所以不会调用原来ActivityA的onNewIntent方法

当ActivityA的LaunchMode为SingleTop时:

如果ActivityA在栈顶,且现在要再启动ActivityA,这时会调用onNewIntent()方法 ,生命周期顺序为:

onCreate--->onStart--->onResume---onPause>onNewIntent--->onResume

当ActivityA的LaunchMode为SingleInstance,SingleTask:

如果ActivityA已经在堆栈中,那么此时会调用onNewIntent()方法,生命周期调用顺序为:

onCreate--->onStart--->onResume---按下Home键>onPause--->onstop--->onNewIntent--->onRestart--->onstart--->onResume

注意:在内存吃紧的情况下,系统可能会kill掉后台运行的 Activity ,如果不巧要启动的那个activity实例被系统kill了,那么系统就会调用 onCreate 方法,而不调用 onNewIntent 方法。这里有个解决方法就是在 onCreate 和 onNewIntent 方法中调用同一个处理数据的方法,

总结:在activityA中设置了对应的启动模式后,其他(自己也行)activityB往A中使用intent跳转,携带值时就会调用onNewIntent()方法,然后是onRestart->onStart()->onResume();

7:Activity的启动过程

启动过程不是启动模式,所谓启动过程,就是从你看到应用图标点击后到正式开启所经过的过程

  • 第一种是从桌面launcher上点击相应的应用图标
  • 第二种是在activity中通过调用startActivity来启动一个新的activity

由于launcher也是一个程序,所以当我们点击应用图标的时候系统会调用startActivitySately()。(具体在第二篇作答)

8:Activity和fragment绑定后流程

fragment存在被activity动态加载和静态加载,静态加载实在xml文件中加载,

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-02-08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Activity生命周期
    • 1:activity四种启动方式
      • 2:Activity正确使用
        • 3:Activity随时随地都可以退出
          • 4:启动Activity最佳写法
            • 5:生命周期以外的方法
              • 恢复您的Activity状态
            • 6:onNewIntent()方法
              • 7:Activity的启动过程
                • 8:Activity和fragment绑定后流程
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档