【Android学习】四大组件-Activity

1,概念

1)activity

activity是一个用户与应用程序进行交互的接口。
一个activity就是一个单独的界面。

2)窗口activity

将一个Activity设置成窗口的样式,只需设置Theme。
①在res/value文件夹下的style.xml文件中加入如下代码:

<style name="Theme.FloatActivity"  parent= "android:style/Theme.Dialog" >  
   <item name="android:windowBackground" > @drawable /float_icon</item>  
</style>  

②在AndroidMainifest.xml中Activity的声明中加入:

android:theme= "@style/Theme.FloatActivity"   

2,生命周期

生命周期有7个:onCreate,onStart,onReStart,onResume,onPause
,onStop,onDestory。
除了这个7个,在一些情况下,还可能经历一个生命周期OnFreeze()。

entire lifetime:整个生命周期;
visible lifetime:可见生命周期;
foreground lifetime:前台的生命周期。
activity生命周期

1)onCreate(Bundle saveInsanceState)方法

i)调用:

activity初始化的时候调用,用于创建Activity。

ii)setContentView(int):

调用此方法填充屏幕的UI:加载界面布局资源、初始化数据。

iii)findViewById(int):

通过此方法返回xml中定义的视图或组件的ID。

iv)参数:

①Bundle类型的数据与Map类型的数据相似,都是以key-value的形式存储数据的。
②saveInsanceState也就是保存Activity的状态的。
③用处:
状态这个参数在实现应用中有很大的用途,比如:
a.一个游戏在退出前,保存一下当前游戏运行的状态,当下次开启时能接着上次的继续玩下去。
b.电子书程序,当一本小说被阅读到第199页后退出了(不管是内存不足还是用户自动关闭程序),当下次打开时,读者可能已忘记了上次已阅读到第几页了,但是,读者想接着上次的读下去。

v)注意:

①子类在重写onCreate方法时,必须调用父类的onCreate方法:super.onCreate,否则抛出异常。
②在onCreate里面耗时长的话会导致极差的用户体验。
③对于布局比较复杂的时候,可以考虑不要一次性全部加载上,动态加载是一个好的办法。

2)onStart()

onStart调用完毕后,activity前台可见,但无法和用户交互。表示Activity正在被启动,即将开始。

3)onResume()

表示Activity已经可见,处于前台并且可操作。
onResume调用后,activity才完全启动,处于运行状态。
onResume是在启动activity启动之后才能执行的,也就是恢复执行。

可在此方法中进行界面的刷新操作(ui恢复后执行)。
注意:onActivityResult()发生在onResume()之前。

4)onPause()

其它activity获得用户焦点,此activity将要进入暂停状态。

注意:此时可以做一些不太耗时的操作:可存储数据、停止动画。
onPause()执行完,新的Activity的onResume才会执行。

5)onStop()

activity不可见,处于停止状态。

注意:可以做一些稍微重量级的回收工作,同样不可太耗时。

6)onDestroy()

activity销毁时调用。

注意:在这里可以做一些回收工作和最终的资源的释放。

Activity退居后台,且系统内存不足时系统会杀死这个后台状态的Activity(此时这个Activity引用仍然处在任务栈中,只是这个时候引用指向的对象已经为null)

7)onRestart()

表示Activity正在重新启动。
当Activity从不可见重新变为可见状态时调用。
在Activity被onStop后,但是没有被onDestroy,在再次启动此Activity时就调用onRestart方法,如果是被onPause但是没有onStop(比如当前是透明的activity或者是消息框什么的),则不会调用 onRestart

8)onFreeze()

即: onSaveInstanceState()和onRestoreInstanceState().
异常情况下的生命周期:activity被系统回收或者由于当前设备的Configuration发生改变从而导致Activity被销毁重建。
当然也可以通过设置configChanges,不调用onFreeze方法。configChanges配置见下文。

异常情况下Activity的重建:
Activity -意外情况->onSaveInstanceState->onDestory-重新创建->onCreate->onRestoreInstanceState.

onSaveInstanceState
i>场景

通常onSaveInstanceState只适合用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。
在activity被杀掉之前调用保存某个实例的状态,以保证该状态可以在onCreate(Bundle)或者onRestoreInstanceState(Bundle) (传入的Bundle参数是由onSaveInstanceState封装好的)中恢复。这个方法在一个activity被杀死前调用,当该activity在将来某个时刻回来时可以恢复其先前状态。

ii>触发

正常情况下不调用,只有异常情况才调用。
调用在onStop之前,与onPause没有既定的顺序。

A.系统内存不足,销毁activity。
B.用户按下HOME键或长按HOME键,选择运行其他的程序时。
C.按下电源按键(关闭屏幕显示或锁屏)时。
D.从activity A中启动一个新的activity时。
当我们在activity A时,此时通知栏有其他的通知,我们点击通知启动activity B,此时我们进入别的应用。
E.配置发生改变(比如横竖屏切换后需要配置不同比例的图片、语言、输入设备等等的改变)

onRestoreInstanceState

将onSaveInstanceState保存的Bundle对象作为参数传递进onRestoreInstanceState和onCreate,从而恢复之前的数据。

根据测试,发现onRestoreInstanceState调用的时间不定,可能在activity的oncreat方法里很多代码都执行完了才调用,依然会造成数据丢失。所以根据实际情况,可能oncreat中读取传入的Bundle参数更好一点。

实现代码如下:

@Override  
protected void onCreate(Bundle savedInstanceState) {  

    if (null != savedInstanceState  
            && (null == UserData.getInstance().getUser()   
            || null == UserData.getInstance().getUser().UserId)){  

        UserInfo user = new UserInfo();  
        user.UserCode = savedInstanceState.getString("UserCode");  
        user.UserName = savedInstanceState.getString("UserName");  
        UserData.getInstance().setUser(user);  
        savedInstanceState = null;  
    }  
    super.onCreate(savedInstanceState);  
}
 /** 
     * 用于保存Activity的状态信息(UI控件的状态信息)和用户保存的信息。 
     * ①用户登录信息:UserCode, UserName 
     */  
    @Override  
    protected void onSaveInstanceState(Bundle outState) {  

        try {  

            outState.putString("UserCode", UserData.getInstance().getUser().UserCode);  
            outState.putString("UserName", UserData.getInstance().getUser().UserName);  

        } catch (Exception e) {  
            System.out.println(Tag + "onSaveInstanceState");  
        }  
    }  

//  @Override  
//  protected void onRestoreInstanceState(Bundle outState) {  
//  
//      try {  
//          UserInfo user = new UserInfo();  
//          user.UserCode = outState.getString("UserCode");  
//          user.UserName = outState.getString("UserName");  
//          UserData.getInstance().setUser(user);  
//      } catch (Exception e) {  
//          System.out.println(Tag + "onRestoreInstanceState");  
//      }  
//  }  

10)事件发生生命周期顺序

必调用的三个方法:onCreate() –>onStart()–>onResume(),用AAA表示。

Activity初次启动或被系统回收后再次打开

AAA

在Activity上显示dialog,Activity调用顺序如下

AAA

程序正常退出:按back 退出、调用finish()

AAA->onPause()->onStop()->onDestory()

因为onDestory了,所以程序按back 退出再进入,相当于重新打开Activity,周期应该为AAA。

父Activity启动子Activity,子Actvity退出,父Activity调用顺序如下

AAA->onFreeze()->onPause() ->onStop() ->onRestart()->onStart()->onResume()

一个Activity启动另一个Activity:
onPause()->onStop()。
注意:在父Activity上显示透明的或非全屏的activity,当前Activity不会调用onStop,周期应该为AAA –>onFreeze –>onPause)

锁屏:onPause()->onStop()
解锁:onStart()->onResume()

用户回到原来的Activity:
onRestart()->onStart()->onResume()。

父Activity打开子Activity时,父Activity调用:onPause()->onStop().
如果新Activity采用了透明主题,那么当前Activity不会回调onStop。
再次回到原Activity,调用:onRestart()->onStart()->onResume()

程序按home 退出:

AAA->onFreeze()->onPause()->onStop()-Maybe->onDestroy()-Maybe。

程序按home 退出再进入(取决于是否调用了onDestroy):
onRestart()->onStart()->onResume()

进入睡眠状态

AAA->onFreeze()->onPause()

11)成对方法

在生命周期的回调里,创建和销毁的代码是否对应起来。(注册和解绑必须一对一出现)。

一般在onResume()注册、onPause()注销。因为onPause()在App死亡前一定会被执行,从而保证广播在App死亡前一定会被注销,从而防止内存泄露。当系统因为内存不足回收Activity时,Activity在执行完onPause()方法后就会被销毁,有些生命周期方法onStop(),onDestory()就不会执行。

①onStart和onStop

从Activity是否可见(不可操作)的角度来回调。可多次调用。

②onResume和onPause

从Activity是否位于前台(可操作)的角度来回调。可多次调用。

③onCreate和onDestroy

标识着Activity的创建和销毁,只会调用一次。

3,activity创建

1)过程

①继承Activity。
当有多个Activity时,建议自己写一个继承Activity的BaseActivity,新建activity的时候,继承BaseActivity即可。
②在AndroidManifest.xml注册activity
③demo: BaseActivity
④标记入口Activity

<intent-filter>
          <action android:name="android.intent.action.MAIN"/>
          <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>

启动Activity有两种,显式调用和隐式调用(<intent-filter>标记入口)。
i>区别
显示调用:Intent启动Acitivity时直接指定要启动的Acitivity名称。
隐式调用:不明确指定启动哪个Activity,而是设置Action、Data、Category,让系统来筛选出合适的Activity。如:

Intent intent = new Intent();  
intent.setAction("abcdefg");  
startActivity(intent);  

ii>隐式调用过滤规则
category部位DEFAULT的Activity不能接受隐式的Intent.

<intent-filter>(过滤规则,不匹配则无法调用)
          <action android:name="android.intent.action.MAIN"/>(可以有多个)
          <category android:name="android.intent.category.LAUNCHER"/>(可以有多个)
          <data mimeType="text/plain"/>(可以有多个)
</intent-filter>

--action 匹配规则
Intent中的action必须能够和过滤规则中的action匹配,即字符串值相同(区分大小写)。action 可以有多个,只要有一个符合即匹配成功。
如果Intent没有action,则匹配失败。
--category 匹配规则
如果Intent含有category,那么所有的category都必须和过滤规则中的其中一个category相同。
如果Intent没有category,匹配成功。
--data 匹配规则
如果过滤规则定义了data ,则Intent中必须有。

data语法:
<data android:scheme="string" URI组成的一部分,URI模式,如:httpfilecontent.
      android:host="string" URI组成的一部分,URI主机名
      android:port="string" URI组成的一部分,端口名
      android:path="string"` URI组成的一部分,完整的路径信息
      android:pathPattern="string" URI组成的一部分,完整的路径信息(可以包含通配符“*”(表示0个多个任意字符 \\*表示真实字符)
      android:pathPrefix="string" URI组成的一部分,路径的前缀信息
      android:mimeType="string" 媒体类型,如:image/jpegaudio/mpeg4-genericvideo/*
      URI格式:<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]

如果要为Intent指定完整的data,必须调用setDataAndType方法(setData和setType方法互相清楚对方的值)

2)问题

①Activity的单例模式

activityA->跳转到activityB. Home键退出后,点击app图标,再次打开应该为activityB,然而却重新打开了activityA。但此时,activityB并没有注销。
解决方案:在BaseActivity中添加如下代码。

    if (!this.isTaskRoot()) { // 判断该Activity是不是任务空间的源Activity,“非”也就是说是被系统重新实例化出来
            // 如果你就放在launcher Activity中话,这里可以直接return了
            Intent mainIntent = getIntent();
            String action = mainIntent.getAction();
            if (mainIntent.hasCategory(Intent.CATEGORY_LAUNCHER) && action.equals(Intent.ACTION_MAIN)) {
                finish();
                return;// finish()之后该活动会继续执行后面的代码,你可以logCat验证,加return避免可能的exception
            }
        }

注意,在AndroidManifest.xml中,第一个启动Activity不要设置成android:launchMode=”singleTask”。

②混淆打包

混淆签名打包后,竟然又出现这个问题!此时需要给启动界面增加如下代码:

if (!isTaskRoot()) {  

    finish();    
    return;    
}  

3)Activity启动方法

①startActivity

startActivity(new Intent(this,Test2Activity.class));

②startActivityFromChild

activity有个属性:parentActivityName。

③startActivityForResult

Activity回调时使用。

4)加速启动Activity

Application 的构造方法,onCreate 方法中不要进行耗时操作,数据预读取(例如 init 数据) 放在异步中操作 启动普通的Activity:A 启动B 时不要在 A 的 onPause 中执行耗时操作。因为 B 的 onResume 方法必须等待 A 的 onPause 执行完成后才能运行

①耗时操作优化

在主线程中执行耗时操作的话会引发ANR异常,所以耗时操作我们需要在子线程完成,还有网络加载数据进行异步请求。
onCreate 方法中不要进行耗时操作、A 启动B 时不要在 A 的 onPause 中执行耗时操作(影响B的onResume方法执行)。

布局文件优化

1.去掉多余控件
2.使用include
3.使用Merge
4.使用ViewStub

③视图加载优化

视图加载优化,最常见的就是我们的Fragment的懒加载,只有显示时才去加载。

4,Activity销毁

1)单个Activity销毁

在第二、三两种情况下,系统可以调用onSaveInstanceState方法,保持activity数据。确保activity在异常情况下崩溃不会丢失数据。

①activity调用finish、或者点击back键

②activity调用onPause和onStop后,被系统强制回收

③配置信息改变。

如:横竖屏切换。

2)多个Activity关闭

①记录打开的Activity

每打开一个Activity,就记录下来。在需要退出的时候,关闭 每一个Activity。

②发送特定广播

在需要结束应用时,发送一个特定广播,每个Activity接收到广播后,关闭 即可。

③递归退出

在打开新的Activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递归关闭。

5,activity通信

1)startActivity

用于把数据传过去。

Intent intent = new Intent();
intent.setClass(this,SetingActivity.class);
Bundle bundle = new Bundle();
bundle.putString("name1","name1");
intent.putExtras(bundle);
startActivity(intent);
Intent intent = getIntent();
Bundle bundle = intent.getExtra();
User user = (User)bundle.get("object");

2)startActivityForResult()

启动一个新的Activity,执行完后返回启动它的 Activity来执行的回调函数。即数据传回来。

①发送方

startActivityForResult(intent,requestCode);
//requestCode:相当于一个id,用于指定这个intent是我发出来的,也就是用于指定我自己的标示。在onActivityResult()方法里面能够进行判断

②接收方

在oncreat方法里面进行接收,然后进行处理,通过setResult把数据返回给发送方。
setResult(resultCode, data);其中resultCode用于标示接收方自己。data是返回的数据,类型是Intent类型

③发送方

此时放送方能够收到数据了,不过要重写onActivityResult方法,方法如下:

protected void onActivityResult(int requestCode, int resultCode, Intent data)

requestCode就是第一步指定的requestCode,resultCode就是第二步指定的resultCode,data就是第二步指定的data。因此在onActivityResult要对前两个参数进行判断,都满足了才能使用第三个参数的数据

④与启动模式的冲突

Android5.0之前,当启动一个Activity时,系统将首先检查Activity的launchMode,如果为A页面设置为SingleInstance或者B页面设置为singleTask或者singleInstance,则会在LaunchFlags中加入FLAG_ACTIVITY_NEW_TASK标志,而如果含有FLAG_ACTIVITY_NEW_TASK标志的话,onActivityResult将会立即接收到一个cancle的信息

在Android5.0做出来修改,系统即便启动的页面设置launchMode为singleTask或singleInstance,onActivityResult依旧可以正常工作。

3)EventBus

4)LocalBroadcastReceiver

6,启动模式

默认情况下,当多次启动同一个Activity时,系统会创建多个实例并把它们一一放入任务栈中。
任务栈是一种后进先出的结构。位于栈顶的Activity处于焦点状态,当按下back按钮的时候,栈内的Activity会一个一个的出栈,并且调用其onDestory()方法。如果栈内没有Activity,那么系统就会回收这个栈,每个APP默认只有一个栈,以APP的包名来命名.

Activity的启动模式有2种写法,如下。

区别在于:
第二种优先级高于第一种。
两者在限定范围上有所不同:如第一种方式无法设定FLAG_ACTIVITY_CLEAR_TOP标识,而第二种方法 无法指定singleInstance模式。

1)android:launchMode

在AndroidManifest.xml中的标签的android:launchMode属性设置四种启动模式:

①standard(标准模式,默认启动模式)

每次激活Activity时(startActivity),都创建Activity实例,并放入任务栈。

②singleTop(栈顶复用模式)

即使栈中已经存在该Activity实例,只要不在栈顶,都会创建实例:
A.如果在任务的栈顶正好存在该Activity的实例, 就重用该实例,同时调用onNewIntent()方法,通过此方法的参数可以获得当前请求的信息。(不会调用onCreate、onStart)
B.否则,创建新的实例并放入栈顶。

场景:
1.适合接收通知启动的内容显示页面。
比如新闻客户端收到了100个推送,你每次点一下推送他都会走一遍某个activiy(显示新闻只用一个activity,只是内容不同而已)的oncreate,onstart,代价就是创建了那么多的activity(不要以为只有推送,比如qq消息提醒)
2.某些业务需求是自己的activity跳转到自己的。
比如 歌曲搜索 你又不会用actionbar,toolbar,那就在activity上面弄个假的呗,搜索完了自己跳转自己现实搜索结果,那就直接用该模式,变化都在onNewIntent()里面对空间进行 赋值之类的。

③singleTask(栈内复用模式,单例模式)

如果要激活的那个Activity在任务栈中存在该实例,则不需要创建,只需要把此Activity放入栈顶,并进行clearTop操作工作:把该Activity以上的Activity实例都pop(弹出销毁)

这个模式可以用来退出整个应用:
将主Activity设为SingTask模式,然后在要退出的Activity中转到主Activity,然后重写主Activity的onNewIntent函数,并在函数中加上一句finish。(因为Activity不创建,所以不会进入onCreate函数,只会进入onNewIntent函数)。

场景:
1,适合程序开始的activity(频繁使用的主架构)
可以用于主架构的activity,(什么新闻啊,侧滑啊)里面有好多fragment,他一般不会被销毁,他可以跳转其他的activity 再回主架构

④singleInstance(单例模式)

是加强的singleTask模式,除了有singleTask的特性外,增加特性:该Activity只能在一个任务栈中(singleTask可以存在于几个不同的任务栈中)。
如果应用1的任务栈中创建了MainActivity实例,如果应用2也要激活MainActivity,则不需要创建,两应用共享该Activity实例;
此启动模式和我们使用的浏览器工作原理类似,我们都知道在多个程序中访问浏览器时,如果当前浏览器没有打开,则打开浏览器,否则会在当前打开的浏览器中访问。此模式会节省大量的系统资源,因为他能保证要请求的Activity对象在当前的栈中只存在一个。

场景:
比如 闹钟里面 负责响的页面,打电话 接通的时候,地图显示的时候,他们都有一个特点 就是你做完这件事了都会返回到上一界面 而没有下一界面。
最好不要把 singleInstance 放到 中间的activity里面:a->b->c 如果 b是该启动模式, 那么 a 、c在一个栈里面,b 在一个栈里面,那你如果回退的话就悲剧啦,用户也会感觉奇怪。

2)Intent Flags

Flags: 表示Intent的标志位,用于指定Activity的启动模式。

Intent intent = new Intent();
intent.setClass(MainActivity.this,SecondActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

①Intent.FLAG_ACTIVITY_NEW_TASK (默认,SngleTask模式)

默认的跳转类型,它会重新创建一个新的Activity。

②FLAG_ACTIVITY_SINGLE_TOP(SingleTop模式)

例如:原来栈中结构是A B C D,在D中启动D,栈中的情况还是A,B,C,D。

③FLAG_ACTIVITY_CLEAR_TOP(类似SingleTask模式)

把要启动的Activity之上的Activity全部弹出栈空间
例如:原来栈中的结构是A B C D ,从D中跳转到B,栈中的结构就变为了A B了。

对比SingleTask:
FLAG_ACTIVITY_CLEAR_TOP会把他上面的弹出,但是自身也销毁,然后重新创建个新对象。而SingleTask不会重新创建新对象,就是不会触发onCreate,只会触发onNewIntent。

④FLAG_ACTIVITY_NO_USER_ACTION

onUserLeaveHint()作为activity周期的一部分,它在activity因为用户要跳转到别的activity而要退到background时使用。比如,在用户按下Home键,它将被调用。比如有电话进来(不属于用户的选择),它就不会被调用。
那么系统如何区分让当前activity退到background时使用是用户的选择?
它是根据促使当前activity退到background的那个新启动的Activity的Intent里是否有FLAG_ACTIVITY_NO_USER_ACTION来确定的。
注意:调用finish()使该activity销毁时不会调用该函数

⑤FLAG_ACTIVITY_NO_HISTORY

这个FLAG启动的Activity,一旦退出,它不会存在于栈中,如:原来是A,B,C这个时候在C中以这个FLAG启动D的,D再启动E,这个时候栈中情况为A,B,C,E。

注意:当调用到onNewIntent(intent)的时候,需要在onNewIntent() 中使用setIntent(intent)赋值给Activity的Intent.否则,后续的getIntent()都是得到老的Intent。

⑥FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

如果设置这个标志,这个Activity不管是从一个新的栈启动还是从已有栈推到栈顶,它都将以the front door of the task的方式启动。这就 将导致任何与应用相关的栈都将重置到正常状态(不管是正在将activity移入还是移除)。

⑦FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

Activity不会出现在历史Activity的列表中,适用于不希望用户通过历史列表回到Activity的情况。
等同于在XML中指定Activity的属性为:android:excludeFromRecents="true"

7,Activity设置

1)android:screenOrientation

android:screenOrientation="portrait"

设为portrait时,无法切换横竖屏。
因此不但不会重新调用各个生命周期方法,而且onConfigurationChanged()方法也不会执行。

2)android:configChanges

根据配置,重启Activity。
相关问题:app中文字标注单位为sp是,当系统的字体大小发生变化的时候,sp的度量标准发生了变化。这时,系统会给app发送一个通知,告诉它配置已经变了,需要重新刷新界面。通过设置fontScale可以进行配置。

--orientation
设备旋转,横向显示和竖向显示模式切换。
--screenSize
屏幕大小改变了.(API13添加)
为了防止屏幕旋转时Activity重启,要加上orientation|screenSize
--keyboardHidden
键盘发生改变,例如,用户使用了硬件键盘
--locale  
语言发生改变,用户选择了一个新的语言,文字应该重新显示
--mcc  
SIM卡唯一标识IMSI中的国家代码,中国为460。此项表示mcc发生变化。
--mnc   
SIM卡唯一标识IMSI中的运营商代码,移动为00,联通01,电信03.此项表示mnc发生变化。
--touchscreen
触摸屏发生改变,这通常是不应该发生的
--keyboard
键盘类型发生改变,例如,用户使用了外部键盘
--navigation
导航发生改变,(这通常不应该发生) 举例:连接蓝牙键盘,连接后确实导致了navigation的类型发生变化。因为连接蓝牙键盘后,我可以使用方向键来navigate了.
--screenLayout
屏幕的布局发生改变,这可能导致激活不同的显示
--fontScale
全局字体大小缩放发生改变
--uiMode
用户界面模式发生了改变。如开启了夜间模式。(API8添加)
--smallestScreenSize
屏幕的物理大小改变了,如:连接到一个外部的屏幕上。(API13添加)
--layoutDirection
布局方向发生变化。(API17添加)

8,Activity入口

1)多个入口

一个app允许有多个入口的存在。
某些情况下,需要为apk设置多个执行入口,也就是安装后在应用程序列表中出现多个图标,各个图标是APP不同模块的入口点,并且各个模块运行在不同的进程中。
因为多个图标共用一个包名,所以只要卸载一个程序,与这个APK包名相同的程序也都会在桌面上消失;
从其它应用跳转到该APK时,需要通过ACTION区分跳转到具体哪一个模块(比如从资源管理器选择一个数据时,到底打开哪一个应用,需要通过action加以区分);
由于多个图标、splash、标题等需要区分的资源都放在一个APK中,这增加了APK的大小。

9,Activity生命周期变化调度流程

调度流程
如:点击跳转一个新Activity A,调度流程应该为:
1)Activity A入栈,它的生命周期:onCreate() –> onResume(),这个过程在ActivityStack里完成,ActivityStack是运行在Server进程里的。此时,Server进程通过ApplicationThread的代理对象ApplicationThreadProxy向运行在app进程ApplicationThread发起操作请求。
2)ApplicationThread接收到操作请求后,因为它是运行在app进程里的其他线程里,所以ApplicationThread需要通过Handler向主线程ActivityThread发送操作消息。
3)主线程接收到ApplicationThread发出的消息后,调用主线程ActivityThread执行响应的操作,并回调Activity相应的周期方法。

注:这里提到了主线程ActivityThread,更准确来说ActivityThread不是线程,因为它没有继承Thread类或者实现Runnable接口,它是运行在应用主线程里的对象,那么应用的主线程到底是什么呢?从本质上来讲启动启动时创建的进程就是主线程,线程和进程处理是否共享资源外,没有其他的区别,对于Linux来说,它们都只是一个struct结构体。

10,性能优化

1)当界面不可见时释放内存,可以重写Activity的onTrimMemory()方法,然后监听TRIM_MEMORY_UI_HIDDEN这个级别,这个级别说明用户离开了页面,可以考虑释放内存和资源。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值