Activity

作者: 沅兮 | 来源:发表于2017-07-11 13:52 被阅读0次

    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文件中的<activity>标签中使用以下几种属性来清理任务栈。
    • 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-filter>
        <action android:name="www.imooc.com">
        <!-- Category属性用于指定当前动作(Action)被执行的环境 -->
        <actegory android:name="android.intent.category.DEFAULT"/>
     </intent-filter>
    
    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<User>(){
        @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设置横竖屏
    <activity
        android:name=".MainActivity"
        <-- protrait为竖屏,landscape为横屏 -->
        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<Activity> activities = new ArrayList<Activity>();
    
        //添加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

        本文链接:https://www.haomeiwen.com/subject/mzxmhxtx.html