android 开发之路(二)

学习移动端开发(比较常用的Android和iOS)第一步你要了解的就是生命周期这个概念。

生命周期有两种:APP的生命周期、视图的生命周期。首先我们来讲下视图的生命周期,即Activity的生命周期

Android官方文档给出的Activity生命周期图

下面简单讲一下Activity生命周期中每个函数的作用:

onCreate() : 

当Activity第一次被创建的时候调用此方法.一般在此方法中进行控件的声明,添加事件等初始化工作.

onStart():

当Activity被显示到屏幕上的时候调用此方法.

onResume():

当此Activity能够被操作之前,也就是能够获得用户的焦点之前调用此方法.

onRestart():

当Activity被停止后又被再次启动之前调用此方法.接着将调用onStart()方法.

onPause():

当第一个Activity通过Intent启动第二个Activity的时候,将调用第一个Activity的onPause()方法.然后调用第二个Activity的onCreate(),onStart(),onResume()方法,接着调用第一个Activity的onStop()方法.如果Activity重新获得焦点,则将调用onResume()方法;如果此Activity进入用户不可见状态,那么将调用onStop()方法.

onStop():

当第一个Activity被第二个Activity完全覆盖,或者被销毁的时候回调用此方法.如果此Activity还会与用户进行交互,将调用onRestart方法();如果此Activity将被销毁,那么将调用onDestroy()方法.

onDestroy():

Activity被销毁之前调用此方法.或者是调用finish()方法结束Activity的时候调用此方法.可以在此方法中进行收尾工作,比如释放资源等.

(注意:重写某个Activity的这些回调方法的时候需要首先在第一行调用基类Activity的相应的回调方法.比如super.onCreate(),super.onStart()等等.)

代码实例:

package com.example.caobotao.activitylifecircle;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i("info","MainActivity onCreate()");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.i("info","MainActivity onStart()");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i("info","MainActivity onResume()");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.i("info", "MainActivity onPause()");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.i("info", "MainActivity onStop()");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i("info","MainActivity onDestroy()");
    }


    @Override
    protected void onRestart() {
        super.onRestart();
        Log.i("info","MainActivity onRestart()");
    }

}

2、其他应用程序中的Activity

我们可以通过ComponentName启动其他应用程序中的Activity,比如启动相机等.

用法:

Intent intent=new Intent();  
intent.setComponent(new ComponentName(String packageName,String activityName ));  
startActivity(intent); 

3、启动系统中常见的Activity

系统给我们提供了很多常用的Activity,可以用来打开浏览器,打开发短信界面,打开相册界面,打开拨号界面等等.

打开浏览器网页:

Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://www.cnblogs.com")); 
startActivity(intent);

打开相册:

Intent intent = new Intent();
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivity(intent);

打开发送短信界面:

Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT,"Hello World !");
startActivity(intent);

打开拨号界面:

Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse("tel:110"));
startActivity(intent);

4、Activity之间的数据交互

我们可以使用Intent对象进行数据的传递.Intent重载了很多putExtra()方法,囊括了JAVA八大基本类型及其数组类型等.

A.actity中传参

 Intent intent = new Intent(Activity1.this,Activity2.class);
 intent.putExtra("name","csdn");
 intent.putExtra("url","www.csdn.com");
 startActivity(intent);

B.actity中接收参数

 Intent intent = getIntent();
 if (intent != null){
     String name = intent.getStringExtra("name");
     int url = intent.getIntExtra("url","www.baidu.com");//"www.baidu.com"为默认值
     Log.i(name, url);
 }

Intent对象还有一个putExtras(Bundle bundle)方法,也就是把所有参数组成一个对象传递(bundle的意思为一捆,就是把需要传递的数据打成一捆进行传递.下面利用Bundle实现上面的示例,接收参数效果一样.

Intent intent = new Intent(Activity1.this,Activity2.class);
Bundle bundle = new Bundle();
bundle.putString("name","zhangsan");
bundle.putInt("age",23);
intent.putExtras(bundle);
startActivity(intent);

在实际开发中,可能需要传递的数据比较多.根据面向对象的思想,我们应该想到把这些信息封装成一个java实体类,以达到更好的复用性,耦合性等目的,然后使用Bundle对象的putSerializable()方法将此需要传递的对象传递出去,在另一个Activity中用Intent对象的getSerializableExtra()方法进行接收.

Person.java

package com.example.caobotao.activitylifecircle;

import java.io.Serializable;

public class Person implements Serializable {
    private String name;
    private int age;
    private String school;
    private String address;
    public Person(){}
    public Person(String name,int age,String school,String address){
        this.name = name;
        this.age = age;
        this.school = school;
        this.address = address;
    }

    @Override
    public String toString() {
        return "姓名: " + name + "\n年龄: " + age + "\n学校: " + school + "\n地址: " + address;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    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 getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }
}

传参

Intent intent = new Intent(Activity1.this,Activity2.class);
Person person = new Person("zhangsan",23,"USST","ShangHai");
Bundle bundle = new Bundle();
bundle.putSerializable("person",person);
intent.putExtras(bundle);
startActivity(intent);

接收参数

Intent intent = getIntent();
if (intent != null) {
    Person person = (Person) intent.getSerializableExtra("person");
    textView.setText(person.toString());
}

5、Task与Back Stack(引自官方文档)

task 是一系列被操作的 activity 的集合,用户进行操作时将与这些 activity 进行交互。 这些 activity 按照启动顺序排队存入一个栈(即“back stack”)。我们知道栈是一个后进先出的数据结构,在一个task中,每打开一个新的activity,就会将其压入栈顶的位置;每次点击Back键,栈顶的activity就会被移除.

大部分 task 都启动自 Home 屏幕。当用户触摸 application launcher 中的图标(或 Home 屏幕上的快捷图标)时,应用程序的 task 就进入前台。 如果该应用不存在 task(最近没有使用过此应用),则会新建一个 task,该应用的“main”activity 作为栈的根 activity 被打开。

当用户返回到 home屏幕执行另一个 task 时,一个 task 被移动到后台执行,此时它的返回栈(back stack)也被保存在后台, 同时 android 为新 task 创建一个新的返回栈(back stack),当它被再次运行从而返回前台时,它的返回栈(back stack)被移到前台,并恢复其之前执行的activity,如下图所示。 如果后台有太多运行 task ,系统将会杀死一些 task 释放内存。

如果当前 activity 启动了另一个 activity,则新的 activity 被压入栈顶并获得焦点。 前一个 activity 仍保存在栈中,但是被停止。activity 停止时,系统会保存用户界面的当前状态。 当用户按下返回键,则当前 activity 将从栈顶弹出(被销毁),前一个 activity 将被恢复(之前的用户界面状态被恢复)。 activity 在栈中的顺序永远不会改变,只会压入和弹出——被当前 activity 启动时压入栈顶,用户用返回键离开时弹出。 这样,back stack 以“后进先出”的方式运行。下图以时间线的方式展示了多个 activity 切换时对应当前时间点的 back stack 状态。

                                     

                图: task 中的每个新 activity 都会相应在 back stack 中增加一项。当用户按下返回键时,

                  当前 activity 被销毁,前一个 activity 被恢复。

如果用户不停地按下返回键,则栈中每个 activity 都会依次弹出,并显示前一个 activity,直至用户回到 Home 屏幕(或者任一启动该 task 的 activity)。 当所有 activity 都从栈中弹出后, task 就此消失。

.Activity启动模式(引自官方文档)

在 manifest 文件中声明 activity 时,你可以利用activity元素的launchMode属性来设定 activity 与 task 的关系。

launchMode 属性指明了 activity 启动 task 的方式。 launchMode 属性可设为四种启动模式:

 

standard(默认模式):

默认值。系统在启动 activity 的 task 中创建一个新的 activity 实例,并把 intent 传送路径指向它。该 activity 可以被实例化多次,各个实例可以属于不同的 task,一个 task 中也可以存在多个实例。

 singleTop:

如果 activity 已经存在一个实例并位于当前 task 的栈顶,则系统会调用已有实例的onNewIntent()方法把 intent 传递给已有实例,而不是创建一个新的 activity 实例。activity 可以被实例化多次,各个实例可以属于不同的 task,一个 task 中可以存在多个实例(但仅当 back stack 顶的 activity 实例不是该 activity 的)。

比如,假定 task 的 back stack 中包含了根 activity A 和 activities B、C、D(顺序是 A-B-C-D;D 在栈顶)。

这时过来一个启动 D 的 intent。如果 D 的启动模式是默认的"standard",则会启动一个新的实例,栈内容变为 A-B-C-D-D。

但是,如果 D 的启动模式是"singleTop",则已有的 D 实例会通过onNewIntent():接收这个 intent,因为该实例位于栈顶——栈中内容仍然维持 A-B-C-D 不变。当然,如果 intent 是要启动 B 的,则 B 的一个新实例还是会加入栈中,即使 B 的启动模式是"singleTop"也是如此。 

注意: 一个 activity 的新实例创建完毕后,用户可以按回退键返回前一个 activity。 但是当 activity 已有实例正在处理刚到达的 intent 时,用户无法用回退键回到 onNewIntent() 中 intent 到来之前的 activity 状态。

singleTask:

系统将创建一个新的 task,并把 activity 实例作为根放入其中。但是,如果 activity 已经在其它 task 中存在实例,则系统会通过调用其实例的onNewIntent() 方法把 intent 传给已有实例,而不是再创建一个新实例。 此 activity 同一时刻只能存在一个实例。

注意: 虽然 activity 启动了一个新的 task,但用户仍然可以用回退键返回前一个 activity。

singleInstance:

除了系统不会把其它 activity 放入当前实例所在的 task 之外,其它均与"singleTask"相同。activity 总是它所在 task 的唯一成员;它所启动的任何 activity 都会放入其它 task 中。

举个例子,Android 的浏览器应用就把 web 浏览器 activity 声明为总是在它自己独立的 task 中打开——把 activity设为singleTask模式。 这意味着,如果你的应用提交 intent 来打开 Android 的浏览器,则其 activity 不会被放入你的应用所在的 task 中。 取而代之的是,或是为浏览器启动一个新的 task;或是浏览器已经在后台运行,只要把 task 调入前台来处理新 intent 即可。

无论 activity 是在一个新的 task 中启动,还是位于其它已有的 task 中,用户总是可以用回退键返回到前一个 activity 中。 但是,如果你启动了一个启动模式设为singleTask的 activity,且有一个后台 task 中已存在实例的话,则这个后台 task 就会整个转到前台。 这时,当前的 back stack 就包含了这个转入前台的 task 中所有的 activity,位置是在栈顶。下图就展示了这种场景。

 

             

          图 . 启动模式为“singleTask”的 activity 如何加入 back stack 的示意图。 如果 activity 已经是在后台 task 中并带有自己的 back stack,则整个后台 back stack 都会转入前台,并放入当前 task 的栈顶。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值