Activity

Activity的生命周期

  • onCreate():创建时调用
  • onStart():在屏幕上可见,但是还没有获取焦点
  • onResume():可见并且获取焦点
  • onRestart():
  • onPause():可见,但是失去焦点
  • onStop():不可见,但是仍然存在内存当中
  • onDestory():销毁了

Activity的重新创建过程

  • Activity非正常结束(如:内存不足、用户直接按Home键),系统会回收activity。此时系统为了补偿你,会将Activity状态通过[onSaveInstanceState()]方法保存到Bundle对象中(可以自己增加额外的键值对保存到Bundle),当需要重新创建此activity时,保存的bundle对象会传递到activity的[onRestoreInstanceState()]方法和onCreate()方法中。这也就是onCreate()方法中参数 -- Bundle savedInstanceState的来源。
  • 主动销毁一个activity时,不调用onSaveInstanceState()
  • 在onPause()方法中持久化数据,在onSaveInstanceState保存瞬态数据,并在onPause()之后调用

AndroidMainifest启动模式

standard
  • 默认的启动模式,栈模式
  • 创建ABB界面:(A)- (AB)-(ABB)
singleTop
  • 当Activity的实例不在栈顶,那么就会创建该Activity的实例,如果已经在栈顶就不会再创建了
  • 创建ABB界面:(A)- (AB)- (AB)
singleTask
  • 如果Activity没有被创建任何实例,那么启动时会创建,如果已经创建了一个实例,那么启动时是返回至该Activity而不会再创建该Activity,并且把该Activity上的实例全部清除。始终保证该栈中永远只有一个该Activity的实例。
  • 创建ABCB界面:(A)-(AB)- (ABC)- (AB)
singleInstance
  • 在单独一个任务栈中创建该Activity的实例,然后再也不会创建第二个实例,以后每次启动该Activity,都是把该Activity所在的栈显示在前台。保证整个系统的内存都只有一个该Activity的实例。来电界面就是该模式。
  • 如果该Activity在前台,按返回键会销毁改Activity,并把该任务栈放置后台,然后会切换到原来的任务栈;如果该Activity的任务栈在后台,不论什么时候启动的,都是在原来的任务栈实例都销毁之后,才会将该任务栈放置前台。
  • 类似浏览器工作原理。多个程序中访问浏览器时,如果浏览器没打开,则打开浏览器,否则会在当前打开浏览器中访问。
Intent设置Flag来设置Activity的启动模式:
  • Intent.FLAG_ACTIVITY_NEW_TASK:使用一个新的Task来启动一个Activity,但启动的每个Activity都将在一个新的Task中,通常该Flag使用在Service中启动activity的场景,由于在service中并不存在Activity栈,所以使用该Flag来创建一个新的activity栈,并创建新的Activity实例
  • Intent.FLAG_ACTIVITY_SINGLE_TOP(singleTop)
  • Intent.FLAG_ACTIVITY_CLEAR_TOP(singleTask)
  • Intent.FLAG_ACTIVITY_NO_HISTORY:使用这种模式启动activity,当该Activity启动其他activity后,该activity就消失了,不会保留在activity栈中。例如A-B,B中以这种模式启动C,C在启动D,则当前activity栈为ABD

清空任务栈

  • 系统提供了清空任务栈的方法来让我们将一个Task全部清除。在AndroidMainifest文件中的标签中使用以下几种属性来清理任务栈。
  • clearTaskOnLaunch:每次返回该Activity时,都将该Activity之上的所有Activity都清除。通过这个属性,可以让这个Task每次在初始化的时候,都只有一个Activity。
  • finishOnTaskLaunch:当离开这个Activity所处的Task,那么用户再返回时, 该Activity就会被finish掉。
  • alwaysRetainTaskState:如果将Activity的这个属性设置为true,那么该Activity所在的Task将不接受任何清理命令,一直保持当前的Task状态。

Activity的启动方式

直接启动
A:
Intent intent = new Intent(this,xxx.class);
startActivity(intent);
B:
Intent intent = new Intent();
ComponentName conmonent = new ComponentName(this,xxx.class);
intent.setComponent(component);
startActivity(intent);
匿名启动 -- 启动系统的Activity
  • 在跳转前的Activity的xml中添加
 
    
    
    
 
Intent intent = new Intent();
intent.setAction("www.imooc.com");
startActivity(intent);

启动系统的Activity

启动系统浏览器
  Intent intent = new Intent();
  intent.setAction(Intent.ACTION_VIEW);
  Uri uri = Uri.parse("http:www.imooc.com");
  intent.setData(uri);
  startActivity(intent);
启动系统图库
  intent.setAction(Intent.ACTION_GET_CONTENT)
  intent.setType("image/*")
发送短信
  intent.setAction(Intent.ACTION_SEND)
  intent.setType("text/plain")
  intent.putExtra(Intent.EXTRA_TEXT,"I now")
启动电话界面
  intent.setAction(Intent.ACTION_CALL)
  Uri uri = Uri.parse("tel:123456");
  intent.setData(url)

Activity的数据交换

传递基本的数据类型
实现Serializable传递对象
  • Serializable的作用是将数据对象存入字节流当中,在需要时重新生成对象。主要应用是利用外部存储设备保存对象状态,以及通过网络传输对象等。
javabean实现Serializable(序列化)接口
Bundle.putSerializable(Key,Object)
getIntent.getSerializableExtra("user");
实现Parcelable传递对象
  • 本质上可以当成一个Serializable,只是Parcelable的对象是在内存中完成的序列化和反序列化,利用的是连续的内存空间,因此更加高效。
### 自定义实体类,实现Parcelable接口,重写其两个方法
@Override
public int describeContents() {
    return 0;
}
// 将对象中的属性保存至目标对象dest中
@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(name);
    dest.writeInt(age);
}
### 创建带有参数的构造方法,本构造方法仅供类的方法createFromParcel调用
public User(Parcel source){
    name = source.readString();
    age = source.readInt();
}
# 该实体类必须添加一个常量CERATOR(名字和大小写都不能是其他的),该常量必须实现Parcelable的内部接口:
  Parcelable.Creator,并实现该接口中的两个方法.
// 必须要创建一个名叫CREATOR的常量。
public static final Parcelable.Creator CREATOR = new Parcelable.Creator(){
    @Override
    public User createFromParcel(Parcel source) {
        return new User(source);
    }
    //重写createFromParcel方法,创建并返回一个获得了数据的user对象
    @Override
    public User[] newArray(int size) {
        return new User[size];
    }
};
为什么要将对象序列化?
  • 永久性保存对象,保存对象的字节序列到本地文件中。
  • 通过序列化对象在网络中传递对象。
  • 通过序列化对象在进程间传递对象。
为什么使用Parcelable接口来实现在Intent中传递对象?
  • 在使用内存的时候,Parcelable比Serializable性能高,推荐用Parcelable类。
  • Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
  • 注意:Parcelable不能使用在将数据存储在磁盘上的情况。因为Parcelable不能很好的保存数据的持续性在外界有变化的情况下。这种情况要使用Serializable。
Activity传递大数据时遇到的问题?
  • bundler传递数据一般不能超过0.5M的内容。
  • 当数据超出后,提示“!!! FAILED BINDER TRANSACTION !!!”红色异常,且Activity界面不再跳转。
  • TransactionToolLargeException传递数据过大异常。

onActivityResult

  • 使用startActivityForResult()方法,参数1为intent,参数2为自己定义的请求码
public void onSelect(View view){
    Intent intent = new Intent(this, ListViewActivity.class);
    startActivityForResult(intent, FLAG_0);
}
  • 第2步:在下个Activity使用setResult()+finish()返回,参数一固定为:RESULT_OK
String number = list.get(position);
Intent intent = new Intent();
intent.putExtra("number",number);
setResult(RESULT_OK,intent);
finish();
  • 第3步:在第一个Activity中处理
 * requestCode 自定的请求码
 * resultCode  setResult()中的结果码:RESULT_OK
 * data        intent
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == FLAG_0 && resultCode == RESULT_OK) {
        String number = data.getStringExtra("number");
        text.setText(number);
    }
}

设置Activity运行时屏幕的方向

  • 通过xml设置横竖屏

    android:screenOrientation="portrait(肖像/竖屏) | landscape(风景/横屏) | sensor(传感器/通过重力感应来判断横竖屏)"
    <-- 横竖屏、屏幕大小、弹出软键盘不销毁重建Activity -->
    android:configChanges="orientation|screenSize|keyboardHidden"h
    android:label="@string/app_name" >
  • 通过代码设置横竖屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);~~~

# Activity全屏

##### 不显示系统的标题栏

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);~~~

不显示程序的标题栏
requestWindowFeature(Window.FEATURE_NO_TITLE);~~~

##### 透明系统的标题栏(沉浸菜单栏)

getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
<-- AndroidManifest.xml中填写,通过theme设置 -->
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"~~~

再按一次退出程序

// 监听返回键
long time = 0;
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount()==0) {
        if (System.currentTimeMillis() - time > 2000) {
            Toast.makeText(this, "再按一次退出系统",0).show();
            time = System.currentTimeMillis();
        } else {
            System.exit(0);
        }
        //此处一定要反回true,否则监听失败
        return true ;
    }
    return super.onKeyDown(keyCode, event);
}

启动Activity的最佳写法

/**
 * 第一个Activity
 */
SecondActivity.actionStart(FirstActivity.this,"data1","data2");

/**
 * 第二个Activity
 */
public static actionStart(Context context,"data1","data2"){
    Intent intent = new Intent(context,SecondActivity.class);
    intent.putExtra("param1","data1");
    intent.putExtra("param2","data2");
    context.startActivity(intent);
}~~~

# 获取当前是哪个Activity

public class BaseActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ getClass:是Object中的方法,表示获取当前对象的类
@ getSimpleName:是Class中的方法,表示获取当前类的名称
Log.d("BaseActivity", getClass().getSimpleName());
}
}~~~

一键销毁所有Activity

  • 首先创建一个管理Activity的管理器
public class ActivityCollector {

    //存储Activity的List
    public static List activities = new ArrayList();

    //添加Activity -- 静态
    public static void addActivity(Activity activity) {
        activities.add(activity);
    }

    //移出Activity -- 静态
    public static void removeActivity(Activity activity) {
        activities.remove(activity);
    }

    // 销毁其他Activity -- 静态
    public static void finishOther(Activity currentActivity){
       for (Activity activity : activities) {
            if (currentActivity != activity && activity.isFinishing()) {
                activity.finish();
            }
        }
    }

    //销毁所有Activity -- 静态
    public static void finishAll() {
        for (Activity activity : activities) {
            if (!activity.isFinishing()) {
                activity.finish();
            }
        }
    }
}
  • 在任何地方调用ActivityCollector.finishAll()就可以销毁所有的activity
public class BaseActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //添加该活动
        ActivityCollector.addActivity(this);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        //删除该活动
        ActivityCollector.removeActivity(this);
    }
}~~~

# Activity的意外回收,处理临时数据

public class MyActivity extends Activity {
//在创建活动时调用,恢复临时数据
@Override
protected void onCreate(Bundle savedInstanceState) { -- 此Bundle就是onSaveInstanceState()保存的数据
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
if (savedInstanceState != null) {
String tempData = savedInstanceState.getString("data_key");
}
}
//在活动意外销毁前一定会被调用,保存临时数据
@Override
protected void onSaveInstanceState(Bundle outState) { -- 进行数据保存
String tempData = "Something you just typed";
outState.putString("data_key", tempData);
}
}~~~

你可能感兴趣的:(Activity)