本文侧重讲解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基础知识等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)