【安卓开发-2】第一次实现Activity的跳转、Activity生命周期、3种正向传值、反向传值

来源:互联网 发布:linux mysql登录命令 编辑:程序博客网 时间:2024/04/30 14:34

1、我们还是先来实践一下,从一个Activity跳转到另一个Activity吧。我们创建一个空Activity的程序,然后新建了一个Activity(Activity本质上是一个java类,只不过它继承了不同的Activity类而已,我们完全可以通过创建普通java类然后继承我们想继承的Activity类,但是我们直接创建Activity的好处就是它会帮我们自动生成一些函数,比如这里的onCreate函数)。

2、我们可以看到创建好AnotherAty之后,它还帮我们自动创建了一个布局文件叫activity_another_aty.xml,并且在AnotherAty里面自动帮我们默认加载这个布局文件。
这里写图片描述

3、我们在MainActivity里面添加一个按钮,其实并不是在MainActivity里面添加,而是在它的布局文件里添加,也就是说在activity_main.xml里添加,由于我们默认的是相对布局,所以这个距离还是需要我们调整一下,不然就把上面文字遮住了:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    ……    <Button        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="跳转到另一个Aty"        android:layout_marginTop="30dp"        android:id="@+id/btnStartAnotherAty"/></RelativeLayout>

4、接下来就是实现功能了,回到MainActivity里面。这里的核心就是通过id找到那个按钮,然后给这个按钮添加一个点击事件监听,如果点击的话,就打开一个Activity,这里用的是startActivity函数,这个函数里面需要的Intent参数,这个后续详细说明,这里不表。

public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        findViewById(R.id.btnStartAnotherAty).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                startActivity(new Intent(MainActivity.this,AnotherAty.class));            }        });    }}

5、从这个简单的程序可以看出来,Activity像是iOS里的控制器,布局像是iOS里的视图。安卓开发这里,我们可以在布局文件里尽情添加控件,但是需要逻辑判断和操作的东西我们都是在Activity里面写的代码,如果需要使用到控件了,在Activity里面用findViewById函数可以找到那个控件(前提是给这个控件得添加id这个属性并赋值)。
这里写图片描述

6、我们刚刚说,MainActivity里面有个onCreate函数,其实这只是Activity生命周期里的一个环节。总结起来一个Activity的生命周期是创建onCreate(),对应的就是摧毁onDestroy()。但是每次创建很耗资源的好不好,所以在不被摧毁的情况下,可以通过开启onStart()、onRestart()和停止onStop()来使用这个Activity。又但是每次开启或者重启也是很好资源的,所以在没有被停止的情况下,我们用恢复onResume()和暂停onPause()来使用Activity。看出来了么?其实这三组是逐层嵌套的,目的就是根据目前Activity的状态来选择资源消耗最少的方式使用,比如这个Activity已经被摧毁了,那没办法了,只能通过创建然后乖乖的一层层开启恢复来使用,但是如果这个Activity没有被摧毁只是不可见了,那么可以通过开启后乖乖的再通过恢复来使用,如果这个Activity只是被另一个Activity“抢镜了”自己被搁置在后面后场的话,那要使用就之用通过恢复即可。具体可以看帮助文档里官方这张生命周期图,很详细。
这里写图片描述

7、 至于2个Activity切换的时候函数的调用顺序,这个自己写一个打印程序就能测试到。假设从A切换到B,一般的顺序是A的onPause()->B的onCreate()->B的onStart()->B的onResume()->A的onStop(),要是再回到A的话,就直接执行A的onRestart()->A的onStart()。为什么说这是一般顺序,因为还有特殊情况,比如B是一个对话框,这个时候其实B出来的时候A还是看的见的,所以顺序就是A的onPause()->B的onCreate()->B的onStart()->B的onResume(),然后关闭B对话框时,执行的是A的onResume(),以及后面B的onPause()->B的onStop()->B的onDestroy()。

8、利用Intent传值(传简单的数据),主要是利用Intent的putExtra()函数来绑定数据。

在MainActivity里:

public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        findViewById(R.id.btnStartAnotherAty).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent i = new Intent(MainActivity.this,AnotherAty.class);                i.putExtra("name","Eric");//绑定数据                startActivity(i);            }        });    }}

在AnotherAty里:

public class AnotherAty extends AppCompatActivity {    private TextView tv;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_another_aty);        Intent i = getIntent();//获取和这个Activity相关的Intent        tv = (TextView) findViewById(R.id.tv);        tv.setText(i.getStringExtra("name"));//利用Intent的getxxxExtra()函数获取数据    }}

9、利用Bundle传递复杂的数据,也就是说把数据放在Bundle里面,然后把Bundle给Intent,获取的时候是从Intent先获取Bundle,然后从Bundle里面取出数据。

在MainActivity里:

public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        findViewById(R.id.btnStartAnotherAty).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent i = new Intent(MainActivity.this,AnotherAty.class);                Bundle b = new Bundle();                b.putString("name","Eric");                b.putInt("age",30);                // 第一种方式                i.putExtras(b);                // 第二种方式                // i.putExtra("data",b);                startActivity(i);            }        });    }}

在AnotherAty里:

public class AnotherAty extends AppCompatActivity {    private TextView tv;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_another_aty);        Intent i = getIntent();        // 第一种获得bundle        Bundle b = i.getExtras();        // 第二种获得bundle        // Bundle b = i.getBundleExtra("data");        tv = (TextView) findViewById(R.id.tv);        tv.setText(String.format("name:%s,age:%d",b.getString("name"),b.getInt("age")));    }}

10、8和9传递的都是一些简单的数据或者通过bundle添加了多个同类型的数据,但是实际开发中我们经常传递的是值对象,比如User类,我们其实一样可以通过Intent绑定这个数据,但是需要这个值对象实现Serializable或者Parcelable。通过实现Serializable比较简单,直接添加实现这个类即可,里面的序列化操作系统会帮我们自己动完成,如下面:

我们的Fuser对象:

package club.finnovate.androidactivity;import java.io.Serializable;/** * Created by Andy on 2016/12/29. */// 实现Serializable接口即可public class Fuser implements Serializable{    private String name;    private int age;    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 Fuser(String name,int age){        this.name=name;        this.age=age;    }}

在MainActivity里:

public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        findViewById(R.id.btnStartAnotherAty).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent i = new Intent(MainActivity.this,AnotherAty.class);                i.putExtra("fuser",new Fuser("Eric",28));//通过构造函数创建                startActivity(i);            }        });    }}

在AnotherAty里:

public class AnotherAty extends AppCompatActivity {    private TextView tv;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_another_aty);        Intent i = getIntent();        // 还是从Intent里获取,只不过是利用getSerializableExtra()函数        Fuser fuser = (Fuser) i.getSerializableExtra("fuser");        tv = (TextView) findViewById(R.id.tv);        tv.setText(String.format("name:%s,age:%d",fuser.getName(),fuser.getAge()));    }}

11、上面利用Serializable简单是简单,但是效率低。所以出现了Parcelable,你可能会猜到,这家伙虽然效率高了,但是操作是复杂了一些。

在Fuser对象里:

package club.finnovate.androidactivity;import android.os.Parcel;import android.os.Parcelable;/** * Created by Andy on 2016/12/29. */// 实现可Parcelable接口并实现里面的2个函数和1个创建public class Fuser implements Parcelable{    private String name;    private int age;    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 Fuser(String name,int age){        this.name=name;        this.age=age;    }    // 第一个函数,不管    @Override    public int describeContents() {        return 0;    }    // 第二个函数,使用writexxx()函数。如果有多个String或者Int的话用writeBundle()函数    @Override    public void writeToParcel(Parcel dest, int flags) {        dest.writeString(getName());        dest.writeInt(getAge());    }    // 1个创建    public static final Creator<Fuser> CREATOR = new Creator<Fuser>() {        @Override        public Fuser createFromParcel(Parcel source) {            return new Fuser(source.readString(),source.readInt());        }        @Override        public Fuser[] newArray(int size) {            return new Fuser[size];        }    };}

在AnotherAty里:

public class AnotherAty extends AppCompatActivity {    private TextView tv;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_another_aty);        Intent i = getIntent();        // 不需要强制类型转换        Fuser fuser = i.getParcelableExtra("fuser");        tv = (TextView) findViewById(R.id.tv);        tv.setText(String.format("name:%s,age:%d",fuser.getName(),fuser.getAge()));    }}

12、Activity的反向传值,也就是通过A跳转到B,再回到A的时候把B里面需要的值反向传递给A供A使用。

在MainActivity里:

public class MainActivity extends AppCompatActivity {    private TextView tv_main;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        tv_main = (TextView) findViewById(R.id.tv_main);        findViewById(R.id.btnStartAnotherAty).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent i = new Intent(MainActivity.this,AnotherAty.class);                // 第二个参数是requestCode,用来标示是哪个按钮或者控件跳转到其他页面的,这个requestCode在下面的函数里是可以获取的,也就是说它还是会回来的                startActivityForResult(i,0);            }        });    }    @Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        super.onActivityResult(requestCode, resultCode, data);        tv_main.setText(data.getStringExtra("name"));    }}

在AnotherAty里:

public class AnotherAty extends AppCompatActivity {    private EditText et_another;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_another_aty);        et_another = (EditText) findViewById(R.id.et_another);        findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent i = new Intent();                i.putExtra("name",et_another.getText().toString());                // 第二个就是返回的数据,还是通过Intent载体传递,第一个是resultCode,用来标示结果状态                setResult(RESULT_OK,i);                // 关闭当前Aty                finish();            }        });    }}
0 0