Activity一些问题

1.Activity的启动流程
Launcher进程请求AMS
AMS发送创建应用进程请求
Zygote进程接受请求并孵化应用进程
应用进程启动ActivityThread
应用进程绑定到AMS
AMS发送启动Activity的请求
ActivityThread的Handler处理启动Activity的请求
在这里插入图片描述
2.onSaveInstanceState,onRestoreInstanceState的调用时机
系统的回收机制会未在用户主动操作的情况下销毁Activity,而为了避免系统回收Activity导致数据丢失,
Android为我们提供了onSaveInstanceState和onRestoreInstanceState用于保存和恢复数据。
系统只在Activity异常终止的时候才会调用onSaveInstanceState和onRestoreInstanceState来储存和恢复数据,正常销毁Activity不会触发这个过程。

onSaveInstanceState:
1.从最近的应用中选择运行其他程序时
2…当用户按下home键时
3.屏幕方向切换时
4.按下电源按键(关闭屏幕显示)时
5.从当前activity启动一个新的activity时:onPause—>onSaveInstanceState—>onStop

onRestoreInstanceState只有在Activity确实被系统回收,重新创建Activity的情况下才会被调用:
比如屏幕方向切换时,activity的生命周期如下
onPause–》onSaveInstanceState–》onStop–》onDestroy–》onCreate–》onStart–》onRestoreInstanceState–》onResume
在这里onRestoreInstanceState被调用,因为Activity确实被系统回收了又重新创建了新的Activity

但是按home键返回桌面又马上点击应用图标回到原来页面时,activity生命周期如下:
onPause–》onSaveInstanceState–》onStop–》onRestart–》onStart–》onResume
因为activity没有被系统回收,因此onRestoreInstanceState没有被调用

3.activity的启动模式和使用场景
standard:默认模式
singleTop:如果要启动的activity已经在栈顶,不会重新创建activity,只会调用该activity的onNewIntent方法;如果要启动的activity不在栈顶,则重新创建该activity实例
singleTask:如果要启动的activity已经存在于栈中,则不会创建该activity实例,将栈中位于该activity上的所有的activity出栈,同时该activity的onNewIntent方法会被调用
singleInstance:创建一个新栈,将要启动的activity压入新栈中,新栈中只会存在这一个activity实例

4.activityA跳转activityB,再按返回键,生命周期执行顺序
A跳转B会执行:A onPause–》B onCreate–》B onStart–》B onResume–》A onStop
在B按下返回键会执行:B onPause–》A onRestart—》A onStart–》A onResume–》B onStop–》B onDestory
当B的launchMode为singleInstance,singleTask且对应的B activity有可复用的实例时,生命周期回调如下:
A.onPause -> B.onNewIntent -> B.onRestart -> B.onStart -> B.onResume -> A.onStop ->
(如果A被移出栈的话还有一个A.onDestory)
当B Activity的launchMode为singleTop且B Activity已经在栈顶时(一些特殊情况如通知栏点击、连点),此时只有B页面自己有生命周期变化B.onPause -> B.onNewIntent -> B.onResume

5.横竖屏切换,按home键,按返回键,锁屏与解锁屏幕,跳转透明Activity界面,启动一个Theme为Dialog的Activity,弹出Dialog时Activity的生命周期
横竖屏切换:
1.不配置Activity的androidconfigChanges,或设置Activity的androidconfigChanges=“orientation”,或设置Activity的android:configChanges=“orientation|keyboardHidden”,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行一次。
2.配置ndroid:configChanges=“orientation|keyboardHidden|screenSize”,才不会销毁activity,且只调用onConfigurationChanged方法。
按home键:
onPause–》onStop–》onRestart–》onStart–》onResume
按返回键:
onPause–》onStop–》onDestory–》onCreate–》onStart–》onResume
锁屏与解锁屏幕:
锁屏只会调用onPause不会调用onStop,解锁屏幕会调用onResume
弹出Dialog:
直接通过WindowManager.addView显示的(没有经过AMS),所以不会对生命周期有任何影响
跳转透明Activity界面,启动一个Theme为Dialog的Activity:
onPause–》onCreate–》onStart–》onResume(Activity不会回调onStop,因为只有Activity切到后台不可见才会回调onStop)

6.onStart和onResume、onPause和onStop的区别
onStart和onResume从Activity可见可交互区分:
onStart用户可以看到部分activity但不能与它交互;onResume可以获得activity的焦点,能够与用户交互
onPause和onStop从Activity是否位于前台,是否有焦点区分
onPause表示当前页面失去焦点;onStop表示当前页面不可见
例如:在activity里面打开一个diaolog的主体页面,该activity会执行onPause但不会执行onStop

7.Activity之间传递数据的方式Intent是否有大小限制,如果传递的数据量偏大,有哪些方案
传512k以下的数据可以正常传递,
传512k~1024K的数据会出错、闪退,
传1024k以上的数据会报错:TranscationTooLargeException
考虑到Intent还包括要启动的Activity等信息,实际可以传的数据略小于512k
数据偏大时的方案:
将数据保存到全局Application中
使用单例数据类
持久化数据

8.Activity的onNewIntent方法什么时候执行
当ActivityA的LaunchMode为SingleTop时,如果ActivityA在栈顶,且现在要再启动ActivityA,这时会调用onNewIntent()方法;
当ActivityA的LaunchMode为SingleInstance,SingleTask时,如果已经ActivityA已经在堆栈中,那么此时再次启动会调用onNewIntent()方法;

9.显式启动和隐式启动
显式启动需要明确地指定被启动对象的组件信息,包括类名和包名
隐式启动是通过在AndroidManifest文件中设置action、data、category,让系统来筛选出合适的Activity
action匹配规则:
intent-filter action可以设置多条
intent中的action只要与intent-filter其中一条匹配成功即可,且intent中的action最多只有一条
intent-filter内必须至少包含一个action
category匹配规则:
intent-filter内必须至少包含一个category,android:name为android.intent.category.DEFAULT
intent-filter category可以设置多条
intent中,category也可以有多条
intent中所有的category都可以在intent-filter中找到一样的才算匹配成功
data匹配规则:
intent-fiter中可以设置多个data
intent中只能设置一个data
intent-fiter中指定了data,intent中就要指定其中一个data

10.scheme使用场景,协议格式,如何使用
scheme是一种页面内跳转协议,是一种非常好的实现机制,通过自己定义的scheme协议可以非常方便的跳转app中的各个页面
测试:
AndroidManifest.xml

        <activity android:name="com.example.testapplication.main.mine.AboutUsActivity"
            android:exported="true">

            <intent-filter tools:ignore="AppLinkUrlError">
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:scheme="https"/>
            </intent-filter>
        </activity>

MineFragment

        //关于我们
        Rl_about_us.setOnClickListener {
            val intent = Intent(Intent.ACTION_VIEW)
            intent.data =  Uri.parse("https://www.baidu.com")
            startActivity(intent)
        }

效果如下:
在这里插入图片描述
将AndroidManifest.xml中修改为
点击效果直接使用浏览器打开网页,不会弹出询问弹窗

11.onCreate和onRestoreInstance方法中恢复数据时的区别
onRestoreInstance不一定会被调用,因为只有被回收再次复用的activity才会回调该方法
onCreate里的Bundle参数可能为空,一定要做非空判断。而onRestoreInstance的Bundle参数一定不会是空值。

12.activity间传递数据的方式
通过Intent传递(Intent.putExtra的内部也是维护一个Bundle,因此,通过putExtra放入的数据取出时也可以通过Bundle去取)
通过全局变量传递
通过SharedPreferences传递
通过数据库传递
通过文件传递

13.跨App启动Activity注意事项
三种跨App启动的方式:
1、通过自定义action启动
WayealmoduleApp.MineFragment

        //关于我们
        Rl_aboutUs.setOnClickListener {
            val intent = Intent()
            intent.action = "transBundle.app"
            startActivity(intent)
//            startActivity(Intent(context, AboutUsActivity::class.java))
        }

TestApplicationApp.AndroidManifest.xml

<activity android:name="com.example.testapplication.main.mine.AboutUsActivity"
            android:exported="true">

            <intent-filter tools:ignore="AppLinkUrlError">
                <action android:name="transBundle.app"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

2.通过在Intent中通过指定包名和类名来查找
WayealmoduleApp.MineFragment

 val componetName = ComponentName(
                "com.example.testapplication",
                "com.example.testapplication.main.mine.AboutUsActivity"
            )
                try {
                    val intent = Intent()
                    intent.component = componetName
                    startActivity(intent)
                }catch (e :Exception){
                    throw e
                }

3、通过scheme启动
WayealmoduleApp.MineFragment

        Rl_aboutUs.setOnClickListener {
            val uri = Uri.parse("app://my.test")
            val intent = Intent("transBundle.app", uri)
            startActivity(intent)
//            startActivity(Intent(context, AboutUsActivity::class.java))
        }

TestApplicationApp.AndroidManifest.xml

        <activity
            android:name="com.example.testapplication.main.mine.modifypwd.ModifyPasswordActivity"
            android:exported="true"
            android:process=".remote">

            <intent-filter>
                <action android:name="transBundle.app"/>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:scheme="app" android:host="my.test"/>
            </intent-filter>
        </activity>

注意: 上述所有被调用的Activity的android:exported="true"一定要设置为true,表示当前Activity可以被另一个Application的组件调用。

14.使用scheme在H5里面调用Activity
h5:

<!DOCTYPE html>
<html>
<head>
    <title>test</title>
</head>
<body>
    <a href="taobao://app/path?query1=1&query2=true">打开APP</a>
</body>
<html>

TestApplicationApp.AndroidManifest.xml

        <activity android:name="com.example.testapplication.main.mine.AboutUsActivity"
            android:exported="true">

            <intent-filter tools:ignore="AppLinkUrlError">
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <category android:name="android.intent.category.APP_BROWSER"/>
                <data
                    android:scheme="taobao"
                    android:host="app"
                    android:path="/path"/>
            </intent-filter>
        </activity>

15.解释一下什么是uid什么是pid
uid: android中uid用于标识一个应用程序,uid在应用安装时被分配,并且在应用存在于手机上期间,都不会改变。一个应用程序只能有一个uid,多个应用可以使用sharedUserId 方式共享同一个uid,前提是这些应用的签名要相同。
pid : 进程ID,可变的

16.Activity任务栈是什么
1.Activity任务栈又称为Task,是一个栈结构,具有先进先出的特性,用于存放我们的Activity组件
2.一个任务栈包含一个Activity的集合,只有在栈顶的Activity才可以和用户进行交互
3.退出应用程序时,必须把所有任务栈中所有的Activity清除出栈时,任务栈才会被销毁。当然任务栈可以移动到后台,并且保留每一个Activity的状态。
4.对应AMS中的ActivityRecord、TaskRecord、ActivityStack

17.Activity有哪些常用的标记位(FLAG)
FLAG_ACTIVITY_NEW_TASK
此标记位作用是为Activity指定“singleTask”启动模式,其效果和在XML中指定相同android:launchMode=“singleTask”

FLAG_ACTIVITY_SINGLE_TOP
此标记位作用是为Activity指定“singleTop”启动模式,其效果和在XML中指定相同android:launchMode=“singleTop”

FLAG_ACTIVITY_CLEAR_TOP
具有此标记位的Activity,当它启动时,在同一个任务栈中位于它上面的Activity都要出栈。此标记位一般会和singleTask启动模式一起出现,此情况下,若被启动的Activity实例存在,则系统会调用它的onNewIntent。

  • 16
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值