您的位置:首页 > 移动开发 > Android开发

Android四大组件之Activity

2016-03-29 10:18 841 查看
做Android开发的没有不知道Activity的,Activity是开发者遇到最频繁, 最多的组件。这里把一些比较不经常用到的知识做一个汇总。

Activity生命周期



引用块内容

要点

onStart(), onResume()为可见状态; onPause(),为部分可见状态; 其他为不可见状态

onSaveInstanceState 保存状态; onRestoreInstanceState恢复状态

Activity 启动模式

Activity启动方式有四种,分别是:

standard

singleTop

singleTask

singleInstance

standard:默认模式,可以不用写配置。在这个模式下,都会默认创建一个新的实例。因此,在这种模式下,可以有多个相同的实例,也允许多个相同Activity叠加。

singleTop: 可以有多个实例,但是不允许多个相同Activity叠加。即,如果Activity在栈顶的时候,启动相同的Activity,不会创建新的实例,而会调用其onNewIntent方法。

例如:若我有两个Activity名为B1,B2,两个Activity内容功能完全相同,都有两个按钮可以跳到B1或者B2,唯一不同的是B1为standard,B2为singleTop。

若我意图打开的顺序为B1->B2->B2,则实际打开的顺序为B1->B2(后一次意图打开B2,实际只调用了前一个的onNewIntent方法)

若我意图打开的顺序为B1->B2->B1->B2,则实际打开的顺序与意图的一致,为B1->B2->B1->B2。

singleTask: 只有一个实例。在同一个应用程序中启动他的时候,若Activity不存在,则会在当前task创建一个新的实例,若存在,则会把task中在其之上的其它Activity destory掉并调用它的onNewIntent方法。如果是在别的应用程序中启动它,则会新建一个task,并在该task中启动这个Activity,singleTask允许别的Activity与其在一个task中共存,也就是说,如果我在这个singleTask的实例中再打开新的Activity,这个新的Activity还是会在singleTask的实例的task中。

例如:

若我的应用程序中有三个Activity,C1,C2,C3,三个Activity可互相启动,其中C2为singleTask模式,那么,无论我在这个程序中如何点击启动,如:C1->C2->C3->C2->C3->C1-C2,C1,C3可能存在多个实例,但是C2只会存在一个,并且这三个Activity都在同一个task里面。

但是C1->C2->C3->C2->C3->C1-C2,这样的操作过程实际应该是如下这样的,因为singleTask会把task中在其之上的其它Activity destory掉。

操作:C1->C2 C1->C2->C3 C1->C2->C3->C2 C1->C2->C3->C2->C3->C1 C1->C2->C3->C2->C3->C1-C2

实际:C1->C2 C1->C2->C3 C1->C2 C1->C2->C3->C1 C1->C2

若是别的应用程序打开C2,则会新启一个task。

如别的应用Other中有一个activity,taskId为200,从它打开C2,则C2的taskIdI不会为200,例如C2的taskId为201,那么再从C2打开C1、C3,则C2、C3的taskId仍为201。

注意:如果此时你点击home,然后再打开Other,发现这时显示的肯定会是Other应用中的内容,而不会是我们应用中的C1 C2 C3中的其中一个。

singleInstance: 只有一个实例,并且这个实例独立运行在一个task中,这个task只有这个实例,不允许有别的Activity存在。

例如:

程序有三个ActivityD1,D2,D3,三个Activity可互相启动,其中D2为singleInstance模式。那么程序从D1开始运行,假设D1的taskId为200,那么从D1启动D2时,D2会新启动一个task,即D2与D1不在一个task中运行。假设D2的taskId为201,再从D2启动D3时,D3的taskId为200,也就是说它被压到了D1启动的任务栈中。

若是在别的应用程序打开D2,假设Other的taskId为200,打开D2,D2会新建一个task运行,假设它的taskId为201,那么如果这时再从D2启动D1或者D3,则又会再创建一个task,因此,若操作步骤为other->D2->D1,这过程就涉及到了3个task了。

Activity传递参数

Intent 传递参数类型:

boolean, char, byte, double,float,int, long, short 基本数据类型及其数组

CharSequence/CharSequence[], String/String[], Bundle

以及实现了 SerializableParcelable 的对象

Serializable: java提供, 所有实现了Serializable的类,都是可序列化类。不需要实现任何方法。

Parcelable:android 特有,效率较高。需要重写 writeToParcel()

选择序列化方法的原则

在使用内存的时候,ParcelableSerializable 性能高,所以推荐使用 Parcelable

Serializable 在序列化的时候会产生大量的临时变量,从而引起频繁的GC。

Parcelable 不能使用在要将数据存储在磁盘上的情况,因为 Parcelable 不能很好的保证数据的持续性在外界有变化的情况下。尽管 Serializable 效率低点,但此时还是建议使用 Serializable

实现Parcelable步骤

implements Parcelable

重写writeToParcel方法,将你的对象序列化为一个Parcel对象,即:将类的数据写入外部提供的Parcel中,打包需要传递的数据到Parcel容器保存,以便从 Parcel容器获取数据

重写describeContents方法,内容接口描述,默认返回0就可以

实例化静态内部对象CREATOR实现接口Parcelable.Creator

例如:

public class MyDemo implements Parcelable {
private int mData;
private int mHaha;

public int describeContents() {
return 0;
}

public void writeToParcel(Parcel out, int flags) {
out.writeInt(mData);
out.writeInt(mHaha);
}

public static final Parcelable.Creator<MyDemo> CREATOR = new Parcelable.Creator<MyDemo>() {
public MyDemo createFromParcel(Parcel in) {
return new MyDemo(in);
}

public MyDemo[] newArray(int size) {
return new MyDemo[size];
}
};

private MyDemo(Parcel in) {
mData = in.readInt();
mHaha = in.readInt();
}
}


Acivity configChanges属性

一般在AndroidManifest.xml文件中都没有使用到 android:configChanges =”orientation|screenSize”配置,当然还是很有用的。

就是如果配置了这个属性,当我们横竖屏切换的时候会直接调用onCreate方法中的 onConfigurationChanged 方法,而不会重新执行onCreate方法,那当然如果不配置这个属性的话就会重新调用onCreate方法了

android:configChanges=[“mcc“, “mnc“, “locale“,

touchscreen“, “keyboard“, “keyboardHidden“,

navigation“, “screenLayout“, “fontScale“, “uiMode“,

orientation“, “screenSize“, “smallestScreenSize“]

mcc: The IMSI mobile country code (MCC) has changed — a SIM has been detected and updated the MCC.

IMSI(国际移动用户识别码)发生改变,检测到SIM卡,或者更新MCC

mnc: The IMSI mobile network code (MNC) has changed — a SIM has been detected and updated the MNC.

IMSI网络发生改变,检测到SIM卡,或者更新MCC

其中mcc和mnc理论上不可能发生变化

locale: The locale has changed — the user has selected a new language that text should be displayed in.

语言发生改变,用户选择了一个新的语言,文字应该重新显示

touchscreen: The touchscreen has changed. (This should never normally happen.)

触摸屏发生改变,这通常是不应该发生的

keyboard: The keyboard type has changed — for example, the user has plugged in an external keyboard.

键盘类型发生改变,例如,用户使用了外部键盘

**keyboardHidden:**The keyboard accessibility has changed — for example, the user has revealed the hardware keyboard.

键盘发生改变,例如,用户使用了硬件键盘

navigation: The navigation type (trackball/dpad) has changed. (This should never normally happen.)

导航发生改变,(这通常不应该发生) 举例:连接蓝牙键盘,连接后确实导致了navigation的类型发生变化。因为连接蓝牙键盘后,我可以使用方向键来navigate了

screenLayout: The screen layout has changed — this might be caused by a different display being activated.

屏幕的布局发生改变,这可能导致激活不同的显示

fontScale: The font scaling factor has changed — the user has selected a new global font size.

全局字体大小缩放发生改变

orientation: The screen orientation has changed — that is, the user has rotated the device.设备旋转,横向显示和竖向显示模式切换。

screenSize: 屏幕大小改变了

smallestScreenSize: 屏幕的物理大小改变了,如:连接到一个外部的屏幕上

layoutDirection属性(),当改变语言设置后,该属性也会成newConfig中的一个mask位。所以ActivityManagerService(实际在ActivityStack)在决定是否重启Activity的时候总是判断为重启。

需要在android:configChanges 中同时添加locale和layoutDirection。

在不退出应用的情况下切换到Settings里切换语言,发现该Activity还是重启了。

Activity windowSoftInputMode

windowSoftInputMode 是来设置窗口软键盘的交互模式, 属性一共有9个取值:

stateUnspecifiedstateUnchangedstateHiddenstateAlwaysHiddenstateVisiblestateAlwaysVisibleadjustUnspecifiedadjustResizeadjustPan

stateUnspecified

中文意思是未指定状态,当我们没有设置 android:windowSoftInputMode 属性的时候,软件默认采用的就是这种交互方式,系统会根据界面采取相应的软键盘的显示模式,比如,当界面上只有文本和按钮的时候,软键盘就不会自动弹出,因为没有输入的必要。那么,当界面上出现了获取了焦点的输入框的时候,当设置属性为stateUnspecified的时候,系统是默认不弹出软键盘的,但是当有获得焦点的输入框的界面有滚动的需求的时候,会自动弹出软键盘。至于为什么非要强调要获取焦点的输入框,这是因为,如果不是输入框获取焦点,软键盘也是不会自动弹出的,让界面不自动弹出软键盘的其中一个解决方案,就是在xml文件中,设置一个非输入框控件获取焦点,从而阻止键盘弹出。

stateUnchanged

中文的意思就是状态不改变的意思,我们应该怎么理解这句话呢?其实很好理解,就是说,当前界面的软键盘状态,取决于上一个界面的软键盘状态。举个例子,假如当前界面键盘是隐藏的,那么跳转之后的界面,软键盘也是隐藏的;如果当前界面是显示的,那么跳转之后的界面,软键盘也是显示状态。

stateHidden

顾名思义,如果我们设置了这个属性,那么键盘状态一定是隐藏的,不管上个界面什么状态,也不管当前界面有没有输入的需求,反正就是不显示。因此,我们可以设置这个属性,来控制软键盘不自动的弹出。

stateAlwaysHidden

当该Activity主窗口获取焦点时,软键盘也总是被隐藏的

stateVisible

设置为这个属性,可以将软键盘召唤出来,即使在界面上没有输入框的情况下也可以强制召唤出来。

stateAlwaysVisible

这个属性也是可以将键盘召唤出来,但是与stateVisible属性有小小的不同之处。举个例子,当我们设置为stateVisible属性,如果当前的界面键盘是显示的,当我们点击按钮跳转到下个界面的时候,软键盘会因为输入框失去焦点而隐藏起来,当我们再次回到当前界面的时候,键盘这个时候是隐藏的。但是如果我们设置为stateAlwaysVisible,我们跳转到下个界面,软键盘还是隐藏的,但是当我们再次回来的时候,软键盘是会显示出来的。所以,这个Always就解释了这个区别,不管什么情况到达当前界面(正常跳转或者是上一个界面被用户返回),软键盘都是显示状态。

说到这里,我联想到了上面的stateHidden和stateAlwaysHidden,我估计区别也是这样的,就是说,stateAlwaysHidden无论如何都是隐藏的,但是如果在跳转到下个界面的时候,软键盘被召唤出来了,那么当下个界面被用户返回的时候,键盘应该是不会被隐藏的,但是,我还没有找到能够跳转到下个界面,还让当前界面软键盘不消失的方法,所以暂时不能验证。

adjustUnspecified

从这个属性开始,就不是设置软键盘的显示与隐藏模式了,而是设置软键盘与软件的显示内容之间的显示关系。当你跟我们没有设置这个值的时候,这个选项也是默认的设置模式。在这中情况下,系统会根据界面选择不同的模式。如果界面里面有可以滚动的控件,比如ScrowView,系统会减小可以滚动的界面的大小,从而保证即使软键盘显示出来了,也能够看到所有的内容。如果布局里面没有滚动的控件,那么软键盘可能就会盖住一些内容。

adjustResize

这个属性表示Activity的主窗口总是会被调整大小,从而保证软键盘显示空间。

adjustPan

当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分

详细参考:http://blog.163.com/ittfxin@126/blog/static/110674863201572513818601/

Activity切换动画

代码

overridePendingTransition(R.anim.scale, R.anim.alpha)


xml 文件

<style name="Animation_Activity" parent="@android:style/Animation.Activity">
<item name="android:activityOpenEnterAnimation">@anim/right_in</item>
<item name="android:activityOpenExitAnimation">@anim/left_out</item>
<item name="android:activityCloseEnterAnimation">@anim/left_in</item>
<item name="android:activityCloseExitAnimation">@anim/right_out</item>
</style>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android