Android Activity

2018-11-10  本文已影响8人  安卓小白之小楼又东风

Android Activity

标签(空格分隔): android


生命周期

Activity生命周期图

此处输入图片的描述此处输入图片的描述

场景:

生命周期设计思想:
1、在多个Activity进行交互的时候,为什么要先暂停(onPause()方法)当前的Activity,执行新的Activity的onCreate()方法,onStart()方法,onResume()方法?
答:比如当你正在一个页面(Activity)上看视频,此时,页面正处于onResume()方法。正在这个时候,突然来了一个电话。此时Android的处理是:首先把第一个视频的页面暂停(onPause()方法),然后再执行第二个页面的onCreate()方法,onStart()方法,onRsume()方法。当第二个页面获得焦点(onResume()方法)的时候,新的页面成功开启的时候,才停止(onStop()方法)第一个页面。如果在新打开的页面onCreate()方法执行之前,就停止(onStop()方法)的话,如果第二个页面由于其它原因开启失败,那就会出现黑屏状态。
2.Activity横竖屏切换:
首先Activity先执行一个生命周期的函数,然后再重新创建一个新的Activity。

onSaveInstanceState-->
onPause-->
onStop-->
onDestroy-->
onCreate-->
onStart-->
onRestoreInstanceState-->
onResume-->

onConfigurationChanged-->
总结:1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次

2、设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次

3、设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
参考自这篇博客

3.onDestory()方法:释放掉与Activity相关的一些属性,为了防止内存泄漏,在优化等方面很重要。

Activity的启动

两种启动方式:隐式启动、显示启动。
应用场景:隐式启动:系统程序或者其他app中的Activity。
显示启动:本app中的Activity。
显示调用

Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
                intent.putExtra("person_data",person);
                startActivity(intent);

隐式调用
manifest

<activity android:name=".SecondActivity">
            <intent-filter>
                <action android:name="www.baidu.com" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

在MainActivity中调用:

Intent intent = new Intent("www.baidu.com");
//onCreate方法
Intent intent = new Intent();
intent.setAction(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);

//manifest里面
<activity android:name=".SecondActivity">
    <intent-filter>
        <action android:name="android.intent.action.DIAL"/>
        <data android:scheme="tel"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

我们观察到intentFilter里面有三种属性:action、category、data
一个Activity可以有多个intent-filter,一个Intent只要能匹配其中一组intent-filter就可以成功启动。
匹配原则:

<data android:scheme="string"
      android:host="string"
      android:port="string"
      android:path="string"
      android:pathPattern="string"
      android:pathPrefix="string"
      android:mimeType="string"/>

data是由两个部分构成,mimeType和URI。
1、minmeType:是指媒体类型。如image/jpeg、audio/mpeg4-generic等。
2、URI:
Scheme:URI的模式。比如http、file、content等。如果参数没有URI没有指定scheme,其他参数无效。
Host:URI的主机名。如果host未指定,整个URI中的其他参数无效,这也意味着URI是无效。
Port:URI中的端口号。
Path、pathPattern、pathPrefix:这三个参数的路径信息。path表示完整的路径信息,pathPattern表示完整的路径信息,但它里面包括通配符“*”。
例子:

intent.setDataAndType(Uri.parse("file://abc"),"image/png");

如果要为Intent指定完整的Data,必须调用setDataAndType方法不能先调用setData在调用setType方法。因为这两个方法会彼此清除对方的值。
源码中

public Intent setData(Uri uri){
   mData = data;
   mType = null;
   return this;
   
}

Activity的启动模式

默认情况下,当我们多次启动后同一个Activity的时候,系统会创建多个实例并把它们放入任务栈,当我们点击back键,会发现Activity一个一个回退。任务栈是一个栈结构,后进先出,当栈空时,系统回收这个任务栈。

<activity android:name=".FirstActivity"
          android:launchMode="singleTask"
          android:configChanges="'screenLayout"
>
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

2、通过Intent中设置标志位指定启动模式:(setClass是运用与本app的跳转,setClassName是用于与不同应用程序的Activity的跳转)。

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

第二种方式的优先级高于第一种方式,两者都存在时,取决于第二种方式。两种方式的限定范围不同。
Android中的Flags:
FLAG_ACTIVITY_NEW_TASK:singleTask
FLAG_ACTIVITY_SINGLE_TOP:sinfleTop
FLAG_ACTIVITY_CLEAR_TOP:singleTask启动模式会具有此标志位效果。
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:相当于android:excludeFromRecents="true".被标记的Activity不会出现在历史列表中。

Actvity传递数据(参考自这篇博客)

1)intent
发送方:

//onCreate方法中
Intent intent = new Intent();
intent.putExtra("name", "诸葛亮");
intent.putExtra("age", 50);
intent.putExtra("IQ", 200.0f);
intent.setClass(MainActivity.this, SecondActivity.class);
startActivity(intent);

接受者:

Intent intent = getIntent();
String name = intent.getStringExtra("name");
int age = intent.getIntExtra("age", 0);
float IQ = intent.getFloatExtra("IQ", 0.0f);
textview2.setText("name:"+name+",age:"+age+",IQ:"+IQ);

2)Bundle
在onCreate方法中的参数就有Bundle。
发送方:

Intent intent = new Intent();
Bundle bundle = new Bundle();
bundle.putString("name", "杨过");
bundle.putInt("age", 30);
bundle.putFloat("weight", 70.9f);
intent.putExtras(bundle);
intent.setClass(MainActivity.this, SecondActivity.class);
startActivity(intent);

接受方:

Intent intent = getIntent();
Bundle bundle = intent.getExtras();
String name = bundle.getString("name");
int age = bundle.getInt("age");
float weight = bundle.getFloat("weight");
textview.setText(name+","+age+","+weight);

3)Application
首先要新建一个继承Application的MyApp类,补充属性的get/set方法

AndroidManifest.xml也要配置application的属性android:name=".MyApp"

发送方:

MyApp myApp = (MyApp) getApplication();
myApp.setName("周星驰");
Intent intent = new Intent();
intent.setClass(MainActivity.this, SecondActivity.class);
startActivity(intent);

接受方:

MyApp myApp = (MyApp) getApplication();
String name = myApp.getName();
textview = (TextView) findViewById(R.id.textview);
textview.setText(name);

4)传递对象用Parclelable接口
首先新建一个对象类:

package com.example.intenttest;

import android.os.Parcel;
import android.os.Parcelable;

import java.io.Serializable;

public class Person implements Parcelable {
    private String name;
    private int age;
    private String hobby;
    //补全get、set方法
    public String getName(){
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getHobby() {
        return hobby;
    }

    public void setHobby(String hobby) {
        this.hobby = hobby;
    }
    //必须重写以下方法
   /**
    * 返回当前对象的内容描述,如果含有文件描述,返回1(常量CONTENTS_FILE_DESCRIPTOR),否则返回0
    * @return
    */
    @Override
    public int describeContents() {
        return 0;
    }
   /**
    * 该方法实现序列化
    * @param dest
    * @param flags 有两个值0(基本上都是0)/1(常量PARCELABLE_WRITE_RETURN_VALUE,表示当前对象需要作为返回值返回,不能立即释放对象)
    */
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(age);
        dest.writeString(hobby);
    }
    public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>(){
    /**
     * 从序列化的对象创建原始对象
     * @param source  序列化后的对象
     *
     * @return
     */
        @Override
        public Person createFromParcel(Parcel source) {
            Person person = new Person();
            person.name = source.readString();
            person.age = source.readInt();
            person.hobby = source.readString();
            return person;
        }
        //初始化原始数组的长度
        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };
}

发送者:

package com.example.intenttest;

import android.content.Intent;
import android.os.PersistableBundle;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ToggleButton;

public class FirstActivity extends AppCompatActivity implements View.OnClickListener{
    Person person = new Person();
    private final static String TAG = "FirstActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_first);
        person.setAge(20);
        person.setName("Jack");
        person.setHobby("football");
        Button sendIntent = (Button)findViewById(R.id.send_intent);
        sendIntent.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.send_intent:
                Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
                intent.putExtra("person_data",person);
                startActivity(intent);
                break;
            default:
                break;
        }
    }

接收者:

Person person = (Person)getIntent().getParcelableExtra("person_data");
textView.setText("年龄:"+person.getAge()+",姓名:"+person.getName()+",爱好:"+person.getHobby());

5)页面返回传值

被返回方:

Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivityForResult(intent, 38);

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    //requstCode邀请码,result返回码;
    super.onActivityResult(requestCode, resultCode, data);
    Bundle bundle = data.getExtras();
    String name = bundle.getString("name");
    int age = bundle.getInt("age");
    float weight = bundle.getFloat("weight");
    Toast.makeText(MainActivity.this, name+age+weight, Toast.LENGTH_LONG).show();
    }

返回方:

Intent data = new Intent();
data.setClass(SecondActivity.this, MainActivity.class);
Bundle bundle = new Bundle();
bundle.putString("name", "张天师");
bundle.putInt("age", 30);
bundle.putFloat("weight", 120.5f);
data.putExtras(bundle);
setResult(250, data);
finish();
上一篇下一篇

猜你喜欢

热点阅读