IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 通过启动Activity来理解Intent+Bundle跨进程 -> 正文阅读

[移动开发]通过启动Activity来理解Intent+Bundle跨进程

从Intent+Bundle到Binder

进程间通信为什么叫IPC?

IPC是Inter-Process Communication 的缩写,意为进程间通讯或跨进程通信,指两个进程之间进行数据交换的过程。

Intent与Bundle之间的关系是什么?

Intent可以携带Bundle类型的对象,然后作为参数传递给AMS,AMS负责启动另外一个Activity或者其他组件。

   //Intent.java源码
    public Intent putExtras(Bundle extras) {
        if (mExtras == null) {
            mExtras = new Bundle();
        }
        mExtras.putAll(extras);
        return this;
    } 

怎么用Intent启动另外一个App的Activity?

方式有几种,详细参考:Android在一个应用程序中启动另一个应用程序
下面其中一种,根据应用的包名,启动它的Activity。可以看到Intent作为参数,最终执行了startActivity(intent);

    private void openApp(String packageName) {
        PackageInfo pi = getPackageManager().getPackageInfo(packageName, 0);

        Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
        resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        resolveIntent.setPackage(pi.packageName);

        List<ResolveInfo> apps = pm.queryIntentActivities(resolveIntent, 0);

        ResolveInfo ri = apps.iterator().next();
        if (ri != null) {
            String packageName = ri.activityInfo.packageName;
            String className = ri.activityInfo.name;

            Intent intent = new Intent(Intent.ACTION_MAIN);
            intent.addCategory(Intent.CATEGORY_LAUNCHER);

            ComponentName cn = new ComponentName(packageName, className);

            intent.setComponent(cn);
            startActivity(intent);
        }
    }

startActivity(intent);中,Intent到底传递给了谁?

ActivityManagerService
整个startActivity()的过程,这篇文章:【Android源码】Intent 源码分析 已经分析的很清楚了,我把跨进程通信相关的部分贴出来。从下面的代码可以看出来intent传递给了ActivityManagerNative.getDefault().startActivity();,而ActivityManagerNative是ActivityManagerService的父类,这个后面的问题会介绍。

public ActivityResult execStartActivity(
       Context who, IBinder contextThread, IBinder token, Activity target,
       Intent intent, int requestCode, Bundle options) {
   IApplicationThread whoThread = (IApplicationThread) contextThread;
   Uri referrer = target != null ? target.onProvideReferrer() : null;
   try {
        // 将Intent数据添加到剪切板上
       intent.migrateExtraStreamToClipData();
        // 准备离开当前进程
       intent.prepareToLeaveProcess(who);
        // 调用ActivityManagerService的startActivity方法
       int result = ActivityManagerNative.getDefault()
           .startActivity(whoThread, who.getBasePackageName(), intent,
                   intent.resolveTypeIfNeeded(who.getContentResolver()),
                   token, target != null ? target.mEmbeddedID : null,
                   requestCode, 0, null, options);
        // 检查并回调给调用者
       checkStartActivityResult(result, intent);
   } catch (RemoteException e) {
       throw new RuntimeException("Failure from system", e);
   }
   return null;
}

启动另一个进程的Activity和AMS有什么关系?为什么要把Intent传递给AMS?

Activity 启动过程是由 ActivityMangerService(AMS) 来启动的,底层原理是 Binder实现的,最终交给 ActivityThread 的 performActivity 方法来启动它。

Binder和AMS是什么关系?

AMS是一个Binder的子类。 AMS继承了ActivityManagerNative,ActivityManagerNative又继承了Binder,所以ActivityManagerService本身就是一个Binder,可以用于进程间通信。

可以得出结论:Intent+Bundle实现跨进程通信,本质还是Binder机制。

AMS属于哪个进程?

System_server进程

启动另一个App的Activity,还需要IPC吗?

现代化操作系统通常具备两种处理器模式:用户模式(User Mode)与内核模式(Kernel Mode)。操作系统(或指操作系统内核)位于内核模式,可管理计算机的全部资源,而处于用户模式的用户进程若需要执行如访问磁盘等特权操作,就需要通过系统调用(System Call)交由内核模式的操作系统执行。

原因很简单,银行是不会让取款的客户进金库自己数钱的。

Android 底层的 Linux Kernel 自然采用了这一权限机制,内核与相关服务运行的内存空间称为内核空间(Kernel Space),而用户进程所运行的内存空间称为用户空间(User Space)。当用户进程通过系统调用进行特权操作时,称此时进程为内核态(Kernel Mode,需注意根据上下文与内核模式进行区分)与用户态(User Mode)。

ActivityManagerService是系统的引导服务,应用进程的启动、切换和调度、四大组件的启动和管理都需要AMS的支持。AMS属于system_server进程,应用进程要和AMS通信,就需要跨进程。

Activity的启动需要做哪些工作?

应用A启动应用B的Activity,属于应用程序的启动或者调度,又AMS负责。下图是Lancher启动某个应用的图解,可以辅助理解应用A启动应用B的Activity的流程。

为什么跨进程通信需要序列化?

android不同的进程都有自己独立的内存空间,且相互之间不能进行访问。如果像我们平常传一个句柄的方式去传值的话肯定是失败的,因为句柄也是指定内存空间的一个区域。现在进程无法访问目标进程的内存空间,所以句柄传过去也是没有用的。
所以我们必须将要传输的数据转换成能够在内存空间流通的形式。这个转化过程就叫做序列化和反序列化。 简单来说是这样的:比如现在我们要将一个对象的数据从客户端传到服务端去,我们就可以在客户端对这个对象进行序列化的操作,将其中包含的数据转化为序列化流,然后将这个序列化流传输到服务端的内存中去,再在服务端对这个数据流进行反序列化的操作,从而还原其中包含的数据。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-04-09 18:32:44  更:2022-04-09 18:34:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 20:41:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码