Android N 四大组件的工作原理

Android N 四大组件的工作原理,第1张

本文侧重讲解android N 系统中四大组件的工作原理,不同系统原理略有差别。通过分析四大组件的工作流程加深对Android Framework的理解,也为插件化开发打下基础。

Activity

展示一个界面并和用户交互,它扮演的是一个前台界面的角色。

Service

计算型组件,用于后台执行一系列计算任务,工作在主线程,耗时 *** 作需要另起线程, 分为启动状态和绑定状态。

BroadcastReceiver

消息型组件,主要用于不同组件或者不同应用之间的消息传递,它工作在系统内部,不适合执行耗时 *** 作, *** 作超过5s,会出现ANR。

ContentProvider

数据共享型组件,用于向其他组件或者应用共享数据,主要执行CURD *** 作。

我们启动一个activity有两种方法

第一种(Activity直接启动方式):

Intent intent = new Intent(this, MainActivityclass);

startActivity(intent);

第二种(Context启动方式)

Intent intent = new Intent(this, MainActivityclass);

getApplicationContext()startActivity(intent);

不同的启动方式Activity的工作流程有点差别。

两种启动都会调用到Instrumentation类中的execStartActivity的方法,系统最终是通过ActivityThread中的performLaunchActivity完成Activity的创建和启动。

performLaunchActivity方法主要完成以下工作:

1、通过ActivityClientRecord对象获取启动activity的组件信息

2、通过mInstrumentation对象的newActivity方法调用classloader完成activity的创建

3、通过rpackageInfo(LoadedApk 对象)的makeApplication方法尝试创建Application对象

4、创建ContextImpl对象并调用Activity的attach方法完成一些数据的初始化

5、调用Activity的onCreate方法

在Activity启动的过程中,App进程会频繁地与AMS进程进行通信:

App进程会委托AMS进程完成Activity生命周期的管理以及任务栈的管理;这个通信过程AMS是Server端,App进程通过持有AMS的client代理IActivityManager完成通信过程;

AMS进程完成生命周期管理以及任务栈管理后,会把控制权交给App进程,让App进程完成Activity类对象的创建,以及生命周期回调;这个通信过程也是通过Binder完成的,App所在server端的Binder对象存在于ActivityThread的内部类ApplicationThread;AMS所在client通过持有IApplicationThread的代理对象完成对于App进程的通信。

Service有两种启动方式,startService()和bindService(),两种状态可以并存:

startService流程

bindService流程

BroadcastReceiver的工作过程主要包括广播的注册、发送和接收:

动态注册过程:

发送过程

静态注册是由PackageManagerService(PMS)在应用安装的时候完成整个注册过程的,除广播以外,其他三大组件也都是在应用安装时由PMS解析并注册的。

每个进程的入口都是ActivityTheadmain(),App的启动流程如下:

从源码中可以看出:

应用启动的入口为ActivityThread的main方法,main方法会创建ActivityThread实例并创建主线程消息队列。

attach方法中远程调用AMS的attachApplication方法,并提供ApplicationThread用于和AMS的通信。

attachApplication方法会通过bindApplication方法和H来调回ActivityThread的handleBindApplication,这个方法会先创建Application,再加载ContentProvider,然后才会回调Application的onCreate方法。

由上图可以看出,在ContentProvider的启动过程中伴随着app进程的启动。

ContentProvider的其他CURD *** 作如insert,delete,update跟query的流程类似。

1概要

startActivity启动一个activity的源码分析,涉及概念较多,比如binder,aidl跨进程通信(ipc),栈管理概念;启动的时序图如下图(来自其他blog)所示:

接下来基于sdk 23 源码里面看看,每个流程分别做了什么。主要分为 APP进程部分 、 Server进程部分 ;

2APP进程(上)

21 Context,ApplicationThread(在ActivityThread里面),Instrumentation

首先启动一个页面,比如activity里面通过contextstartActivity,会调用到startActivityForResult方法,接着会调用Instrumentation的execStartActivity方法,里面有几个入参需要注意的,第一个context自身,一个是ApplicationThread(它是一个binder本地对象,或者说是server对象,它是抽象类ApplicationThreadNative的实现类,具体能力的承载类,为后续AMS持有它的proxy进行启动activity使用),还有一个参数intent(传递参数);

22 ActivityManagerNative,ActivityManagerService(AMS),ActivityManagerProxy(asInterface,它入参就是从sm那里拿来的binder代理对象),ServiceManager,

ServiceManager只是一个装饰类,最终调用的方法是binder内核驱动的方法,是通过BinderInterner里获取的binder对象,如:addService,registerService等方法。它对应的也有serviceManagerNative等,所有的binder服务(AMS/PMS/)等都是从这边获取到对应client对象。

通过ActivityManagerProxystartActivity,他的里面调用transact,接着通过binder IPC进入AMS;到此为止都是在 APP进程中

3Server进程

-------------------- Server进程部分 -------------------

该部分主要是做一些启动前的校验,创建和管理Activity stack ,创建进程,绑定ApplicationThreadProxy

31 AMNonTransact

接下来我们就在, AMN是个抽象类,是个System server进程里面的本地服务,onTransact方法被调用,里面是真正的StartActivity方法的实现是在AMS中。

32 AMSonTransact

在里面会调用startActivityAsUser,在SDK 23中是进入ActivityStackSupervisor,24中进入ActivityStarter的startActivityMayWait。

ActivityStackSupervisor 为了多屏而出现,管理多个ActivityStack

33 ASSstartActivityMayWait

这个方法的作用主要是获取ActivityInfo信息(如果有多个activity会d框让用户选择),里面会经过PMS获取ActivityInfo信息,并保存在intent对象中,接着进入startActivityLocked,它的返回值里,如果大于等于0标识启动成功,小于零标识启动失败。

34 ASSstartActivityLocked

该方法会进行一系列的常规检查,比如activity是否在AndroidManifest注册,是否存在这个activity等等,常规检查通过之后,会进行权限的检查;如果在都成功的情况下,进行ActivityRecrd(一个Activity可以对应多个ActivityRecord)的创建;并校验App切换是否允许,如果不允许则要启动的Activity添加到pending中,并直接返回,相当于检查下是否又被阻塞的activity,优先启动。

35 ASSstartActivityUncheckedLocked (栈管理相关的 *** 作)

这个阶段就不需要做些权限的检查;这个函数的主要作用就是找到或者创建新的Activity所属于的task对象,之后调用ActivityStack的startActivityLocked。其中会根据我的ActivityRecord的属性,从标签中获取,进行Standard、singleTop、singleTask、singleInstance相关要求的处理。比如是否需要新建栈,或者 已有 栈中是否存在此Activity,如果应用之前 没有 起来过,那找不到task如何处理等等。

如果不存在该Activity,则需要创建进入

ActivityStack (栈的管理,activity是否显示等等)

36 ASstartActivityLocked

入参里面,ActivityRecord,是否需要立马显示,是否需要创建新的task等等。

如果新启动一个app,表示宿主栈ActivityStack中没有历史任务,或者强制要求在新的任务中启动Activity, 既然是一个新任务,那么就需要需要将任务插入宿主栈顶。放入并放在栈顶之后,将Activity推入显示状态。

37 ASresumeTopActivityLocked-> resumeTopActivityInnerLocked

找到第一个没有finishing的栈顶activity,找不到直接回到桌面,找到了,就执行startPausingLocked暂停activity,接着进入startSpecificActivityLocked

38 ASresumeTopActivityInnerLocked

尝试将ActivityRecord迁移到显示状态(Resumed),如果发现待显示的Activity的宿主进程可能没有启动,则需要回到ASSstartSpecificActivityLocked。

ActivityStackSupervisor

39 ASS startSpecificActivityLocked

如果通过包名,发现才宿主进程不存在,则启动一个新的应用进程。这时候会调用AMSnewProcessRecord来创建一个新的ProcessRecord,然后再调用另外一个重载的AMSstartProcessLocked()函数,来创建一个进程。进入AMSstartProccesslocked。 如果已经存在则直接进入realStartActivityLocked方法,进行启动activity。

ActivityManagerService

310 AMSstartProccesslocked (参考: >

一、activity

1一个activity就是一个类,继承activity;

2需要复写onCreate()方法;

3每一个activity都需要在AndroidMainfestxml清单上进行配置;

4为activity添加必要的控件

二、布局

线性布局:LinearLayout

1填满父空间:fill_parent、match_parent

2文本多大空间就有多大:warp_content

3文字对齐方式:gravity

4占屏幕的比例:layout_weight="1"  水平方向,则width=0,垂直方向,则height=0

5一行显示,空间不够会省略:singleLine="ture"  false会换行

6背景:background="#ffffff"

7水平布局:orientation="horizontal"

垂直布局:orientation="vertivcal"

表格布局:TableLayout

1内边距:padding

2外边距:marginLeft\Start、Right\End、Top、Bottom

三、RelativeLayout相对布局

layout_above 将该控件的底部置于给定ID控件之上

layout_below 将该控件的顶部置于给定ID控件之下

layout_toLeftOf 将该控件的右边缘和给定ID控件的左边缘对齐

layout_toRightOf 将该控件的左边缘和给定ID控件的右边缘对齐

layout_alignBaseline 该控件的baseline和给定ID的控件的Baseline对齐

layout_alignBottom 该控件的底部边缘和给定ID的控件的底部边缘对齐

layout_alignLeft 该控件的左边缘和给定ID的控件的左边缘对齐

layout_alignRight 该控件的右边缘和给定ID的控件的右边缘对齐

layout_alignTop 该控件的顶部边缘和给定ID的控件的顶部边缘对齐

layout_alignparentBottom 如果该值为true,则该控件的底部和父控件的底部对齐layout_alignParentLeft 如果该值为true,则该控件的左边和父控件的左边对齐

layout_alignParentRight 如果该值为true,则该控件的右边和父控件的右边对齐

layout_alignParentTop 如果该值为true,则该控件的上边和父控件的上边对齐

layout_centerHorizontal 如果该值为true,则该控件将被置于水平方向的中央

layout_centerInParent 如果该值为true,则该控件将被置于父控件水平和垂直方向的中央

layout_centerVertival 如果该值为true,则该控件将被置于垂直方向的中央

四、一个Intent对象包含一组信息

1Component name

2Action

3Data

4Category

5Extras

6Flags

Intent intent = new Intent(this, SecondActivityclass);

startActivity(intent);  //startActivity方法

intentputExtra("Key", "Value");  //键值对

intent = getIntent();

String value = intentgetStringExtra("Key");    //通过键提取数据

五、初级控件:EditText、TextView、Button

1获取EditText的值

String value = EditTextgetText()toString();

2将值放到Intent对象中

Intent intent = new Intent();

intentputExtra("one",value )

intentsetCalss(Activitythis, OtherActivityclass);

3使用这个Intent对象来启动Otheractivity

ActivitythisstartActivity(intent);

4将监听器的对象绑定到按钮对象上

buttonsetOnclickListener(new Listener());

5得到Intent对象当中的值

Intent intent = getIntent();

String value1 = intentgetStringExtra("one");

int value2 = IntegerparseInt(value);

六、其他初级控件使用

①ImageView

②RadioGroup和RadioButton

setOnCheckedChangeListener(new RadioGroupOnCheckedChangeListener())

③Checkbox

setOnCheckedChangeListener(new CompoundButtonOnCheckedChangeListener())

④Menu

1当客户点击MENU按钮的时候,调用onCreateOptionMenu()方法

public boolean onCreateOptionMenu(Menu menu){

menuadd(0,1,1,Rstringid);

}

2当客户点击MENU内部的具体某一个选项时,调用onOptionItemSelected()方法

public boolean onOptionItemSelected(MenuItem item){

if(itemgetItemId() == 1){

finish();

}

return superonOptionItemSelected(item);

}

七、Activity的生命周期

1第一次创建时调用

protected void onCreat(Bundle saveInstanceState);

2显示出来时调用

protected void onStrat();

3获得用户焦点时调用(可 *** 作)

protected void onResume();

4点击d出第二个Activity时调用

protected void onPause();

5当第一个Activity不可见时调用

protected void onStop();

6当返回第一个Activity时调用,代替OnCreate,因为没被销毁

protected void onRestart();

7当返回第一个Activity时调用(先执行onStop,在执行,因为第二个Activity被销毁,不能返回获取,只能通过onCreat,onStart,onResume再创建)

protected void onDestory();

八、Task

1Task是存放Activity的Stack栈。当点击启动第二个Activiry时,第一个Activtiy会被压入Stack栈当中,第二个Activity会位于栈的顶部;当返回第一个Activtiy时,第二个Activity会被d出Stack,第一个Activity会位于栈的顶部,以此类推。

注释:当调用finish()时,当前的Activity会被Destory掉,栈中的Activity会消失。

2当Activity都从Stack退出后,则就不存在Task。

九、高级控件

①进度条ProgressBar

水平进度条style="android:attr/progressBarStyleHorizontal"

圆圈进度条style="android:attr/progressBarStyle"

用户可视的visibility="gone"

②列表ListView

十、其他控件

A下拉菜单Spinner

1创建一个ArrayAdapter:

ArrayAdapter<CharSequence> adapter = ArrayAdaptercreateFromResource(

this, //指上下文对象

Rarrayplant_array, //引用了在文件中定义的String数组

androidRlayoutsimple_spinner_item);//用来指定Spinner的样式,可替换自定义

adaptersetDropDownViewResource(

androidRlayoutsimple_spinner_dropdown_item);//设置Spinner当中每个条目的样式

2得到Spinner对象,并设置数据:

spinner=(spinner)findViewById(RidspinnerId);

spinnersetAdapter(adapter);

spinnersetPrompt("测试");//标题

3创建监听器

class SpinnerOnSelectListener implements OnItemSelectedListener{

@override

public void onItemSelected(

AdapterView<> adapterView,//整个列表对象

View view,//被选中的具体条目对象

int position,//位置

long id){ //id

String selected = adapterViewgetItemAtPosition(position)toString();

}

@override

public void onNothingSelected(AdapterView<> adapterView){

Sop("nothingSelected");

}

}

4绑定监听器

spinnersetOnItemSelectedListener(new SpinnerOnSelectListener());

注:第二种动态设计

1创建ArrayList对象

List<String> list = new ArrayList<String>();

listadd("test1");

2 调用方法

ArrayAdapter adapter = new ArrayAdapter(

this, //指上下文对象

Rlayoutitem, //引用了指定了下拉菜单的自定义布局文件

RidtextViewId,//id

list);//数据

3得到Spinner对象,并设置对象

spinnersetAdapter(adapter);

spinnersetPrompt("测试");//标题

3创建监听器

class SpinnerOnSelectListener implements OnItemSelectedListener{

@override

public void onItemSelected(

AdapterView<> adapterView,//整个列表对象

View view,//被选中的具体条目对象

int position,//位置

long id){ //id

String selected = adapterViewgetItemAtPosition(position)toString();

}

@override

public void onNothingSelected(AdapterView<> adapterView){

Sop("nothingSelected");

}

}

4绑定监听器

spinnersetOnItemSelectedListener(new SpinnerOnSelectListener());

BDatePicker和DatePickerDialog

1声明一个监听器,使用匿名内部类

DatePickerDialogOnDateSetListener onDateSetListener

= new DatePivkerDialogOnDateSetListener(){

public void onDateSet(

DatePicker view,

int year,

int monthOfYear,

int dayOfMonth){

Sop(year+"-"+motnOfYear+"-"+dayOfMonth)

}

}

2复写onCreateDialog(int id)方法:

@override

protected Dialog onCreateDialog(int id){

switch(id){

case DATE_PICKER_ID:

return new DatePickerDialog(this,onDateSetListener,2019,11,25);

}

return null;

}

3使用时调用showDialog()方法

showDialog(DATE_PICKER_ID);

CAutoCompleteTextView

BWidget

CAnimatin

十一、实现ContentProvider过程

1定义一个CONTENT_URI常量

2定义一个类,继承ContentProvider

3实现query、insert、update、delete、getType和onCreate方法

4在AndroidManifestxml当中进行声明

以上就是关于Android N 四大组件的工作原理全部的内容,包括:Android N 四大组件的工作原理、startActivity简解、Android基础知识等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9800558.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-02
下一篇 2023-05-02

发表评论

登录后才能评论

评论列表(0条)

保存