Android开发笔记: android四大组件之Activity

一,什么是Activity? 活动

Activity:一个单独的屏幕 一个显示的窗口 一个界面
定义:用来显示android应用的界面的一个组件!!!

什么是android组件:
android应用:主要由4大组件构成
组件:创建  销毁 :一个组件从创建到销毁的过程:生命周期
不同的组件功能不同
android的四大组件:
Activity(界面)----接待
BroadCastReceiver(广播)---品牌
Service(服务)---做服务
ContentProvider(内容提供者)---真正提供具体服务
用户:服务

NOTO:anroid组件都必须在清单文件中注册

二,怎么样在清单文件中注册组件:

<activity
            android:name="com.tz.katehome.MainActivity"  activity名字
            android:label="@string/app_name" > activity的标签
        </activity>
意图过滤器:找到组件
 <intent-filter>
                <action android:name="android.intent.action.MAIN" />


                <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
 上面的代码作用:指定我们当前的android应用第1个启动的activity


三,Activity的生命周期

        (官方文档 :1,翻墙软件  2,国内的镜像 3,sdk--dosc目录)

国内的镜像:http://wear.techbrood.com/guide/components/activities.html



onCreate,创建activity

onStart,可以看到activity

onResume,获取焦点,用户可以进行交互

onPause,失去焦点,被其他activity部分遮挡

onStop ,不可见activity

onDestroy, 销毁activity


onPause->onResume, 弹出的activity退出时,主activity会进入onResume方法


onStop->onRestart->onStart



四,Activity的启动方式:(启动模式)

(1)显示启动activity,只能启动当前应用activity

//一个activity启动另一个actiivty,只能在当前应用启动activity

  //:Intent意图--四大组件的纽带

//参数:1,当前activity的context  2,启动得到Activity的.class
//activity启动1
//Intent intent = new Intent(this,OtherActivity.class);
//activity启动2
Intent intent = new Intent();
//intent.setClassName(this,"com.tz.activitylifecycle.OtherActivity");
//activity启动3
//intent.setClassName(getPackageName(),"com.tz.activitylifecycle.OtherActivity");
//activity启动4
//intent.setClass(this, OtherActivity.class);
//activity启动5  Component :组织 组件
ComponentName component = new ComponentName(this, OtherActivity.class);
intent.setComponent(component);

(2)隐式启动 ,跨进程启动activity

        意图过滤器---不同应用之间来启动Actvity(其他组件)
Intent是基于消息通讯机制

<intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

上面这的action和catetory是用来配置应用的第1个启动的Actvit的(可以配置多个,但是会启动xml中的第1个)


Intent-filter:包含两个部分

1,目的【action】--------要到哪里去
2,内容【category,data】------去的路上要带什么,区分性数据和内容性数据
意图过滤器的配置:

1,action+category

总结:
(1),所有的activity的过滤器都必须设置(但是第1个启动的activity不必)
<category android:name="android.intent.category.DEFAULT"/>
(2),在startActivity(Intent intent)方法内部默认设置了category的值为
android.intent.category.DEFAULT"
(3),(在没有设置数据)只要intent中action和category都出现在Intent-Filteer中就能与之匹配,
否者匹配失败

2,actoin+data

URI:统一资源标示 跟网址的组成部分是一样
Uri:  tzEdu://www.tanzhou.com/kate

uri格式:http://blog.csdn.net/sunny09290/article/details/7514963

URL:统一资源定位  http://www.baidu.com/index.html/3(网址)
http://   -----scheme   主题
www.baidu.com  ---host  主机地址
index.html    ----path 路径
3 -----id

总结:
1)如果在Intent-filter中制定了data,如果要匹配到此Activity,必须在
 intent中设置data,否者匹配不到

2)Scheme属性没有指定,其他属性都无效,host没有指定 port path都无效

            

3 action+data+miniType

<data android:scheme="tzEdu" android:host="www.tanzhou.com" 
                    android:path="/kate"  注意path一定要加 //>
                <data android:mimeType="image/*"/>

1)当有data和miniType同时存在,不要单独通过 setData() 和setType()方法进行设置
要通过setDataAndType()同时设置数据和类型才可以匹配

4 action + minaType

<data android:mimeType="image/*"/>
 
intent.setType("image/png");


五,设置点击事件:

(1)xml布局中为要设置点击事件的控件加属性:
android:onClick="startOther"

然后在activity中定义startOther(View v){}方法


(2)activity作为监听器
在Activity获取控件对象,然后通过setOnClickListener(this);
  Activity实现OnClickListener接口 然后重写接口的onClick方法


(3)匿名内部类监听器
start.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {

}
});
(4)重写监听器类  实现OnClickListener接口


btn_start.setOnClickListener(new MyOnclicklistener());


public class MyOnclicklistener implements View.OnClickListener{


    @Override
    public void onClick(View v) {


    }
}


(5)注解的方式(ioc)


六 activity模式

Activity一共有以下四种launchMode:

1.standard

2.singleTop

3.singleTask

4.singleInstance

作用概述:规定是否新建activity,是否公用task(task:应用启动时,会创建一个对应的task。task主要负责对activity进行管理。)

使用方法:我们可以在AndroidManifest.xml配置<activity>的android:launchMode属性为以上四种之一即可,默认情况下为标准模式。



第一种模式:standard

这是系统默认的启动模式,即:不用再在AndroidManifest.xml配置<activity>的android:launchMode。

作用:标准模式下,只要用intent 跳转,系统会自动创建一个新的activity实例,并且放在栈顶。按下回退键,系统会从顶部开始一个一个清除Activity。



第二种模式:singleTop

作用:singleTop模式下,如果要跳转的activity的实例已经在栈中存在,看其是否位于栈顶,如果位于栈顶,则直接启用旧的,不在创建实例,如果不在栈顶,则创建一个新的实例。



第三种模式:singleTask

作用:如果要启动的activity的实例不存在,则创建一个新的实例。如果要启动activity的实例在栈中已经存在,则清除此activty旧实例以上的所有activity,启动旧activity的实例并且至于栈顶,开始执行OnResum()方法。



问题:启动模式为singletask,activity无法获取到intent的传值问题。

原因:

1.启动一个为启动过的activity ,会获取到新的 intent。也就是说就是启动模式设置为:singletask,第一次启动界面是传递的数据是可以接受到的。

2.当此界面再次被启动时,因为他的启动模式是:singletask,所以不会重新创建一个activity,而是启动旧的activity实例,通过getIntent()方法获取到的 intent 也是旧的Intent,没有携带新的数据。所以无法获取到数据。

解决方法:重写这个方法,并且把调用setIntent(intent),对Intent进行更新。此方法在activity(启动模式为:singletask)的界面第二次启动时,在onresume()方法之前被回调。

         @Override
protected void onNewIntent(Intent intent) {
// TODO Auto-generated method stub
super.onNewIntent(intent);
setIntent(intent);
}




第四种模式:singleInstance

作用:系统会重新启用一个栈,并且把这个activity放入新的栈中,并且保证不会再让其他的activity进入。再次跳转该activity,activity如果存在则直接启用,不存在创建新的。

注意:5.0以上的部分手机,一个应用存在多个栈的情况下,切到后台,后台会出现多个后台同一个应用的界面,这是因为界面不在同一个栈中。




七  Activity栈(Task)的相关知识总结:


1.Activity的affinity(亲和力)

2.Intent几种常见的flags

3.<activity>与task相关属性


第一个: Affinity(密切关系

在系统默认情况下,打开一个app,系统默认包名为affinity的值。task自身的affinity的值取决于根activity的affinity。具有相同的affinity的activity同属于一个task。


实例1:

           建立两个demo App分别命名为 A 和 B。从 A 的主界面通过意图跳转到 B 的主界面界面。此时两个app的界面位于同一个App A的栈内。如图:



           

第二个:  Intent 常用的 flag:

1.FLAG_ACTIVITY_NEW_TASK    根据Activity 的 affinity去寻找task 栈。如果一个task 的 affinity与 activity 的 affinity的相同,则                                                                      Activity会压入栈中。如果没有找到相同的,则新建立栈,并且把activity压入栈中。

实例1: 从App  A主界面跳转到 App B主界面。给Intent添加FLAG_ACTIVITY_NEW_TASK    标识。

             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);


               

结果会建立两个栈。App A 的界面在App A 的栈里。App B 的界面在 App B 的栈里边。


实例2:在实例1 的基础上,在App B里添加代码,给App B的主界面 在manifest 中添加  


  <activity
            android:name="com.example.b.MainActivity"
            
android:taskAffinity="com.example.a"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="hello" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>


com.example.a为App A 的包名。这样的结果是 App A 和App B的界面会在同一个栈里。



2.FLAG_ACTIVITY_CLEAR_TOP  检查栈内是否存在要启动的Activity实例,如果存在实例,则会调用旧的Activity实例,并且清除此Activty                                                        上面的所有的activty,使其至于栈顶显示出来。

注意:1. intnet.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 跳转的页面会从 OnCreate()方法开始执行。

           2.FLAG_ACTIVITY_CLEAR_TOP  相当于 加载模式的 signleTask


3.FLAG_ACTIVITY_SINGLE_TOP  相当于加载模式的  signleTop

4.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET   如果Intent 包含此属性,那么,要跳转的activity和次activity上的所有界面,都会在task重置时被清除。(待定)


5.FLAG_ACTIVITY_NO_HISTORY  如果Intent 包含此属性,那么,要启动activity 将显示一次,不会再task栈内保存。

6.FLAG_ACTIVITY_REORDER_TO_FRONT    把已经存在的界面拿到栈顶,

例:ABCD已经存在,D通过FLAG_ACTIVITY_REORDER_TO_FRONT    去启动A,则栈内顺序BCDA。

7.FLAG_ACTIVITY_BROUGHT_TO_FRONT(测试不起作用)


八,Activity之间数据的传递

Activity之间传数据
* 1,基本类型和数组

* 2, 传对象     a,bundle对象(andoid写好的)

* b,自定义的对象:序列化  java中用:Serializable  不可以跨进程  
* android中用:Parcelable 可以跨进程
NOTE: parcelable序列化的时候,write属性的顺序必须和read的顺序一致
* android中推荐使用:Parcelable

  自定义对象要implements Serializable 或者Parcelable

                 Serializable:简单,不需要实现方法,不跨进程

                 Parcelable:复杂,需要实现相关方法,且读写对象顺序要一致,跨进程

传递图片的bitmap
intent.putExtra("bitmap",bitmap);

Bitmap bitmap = intent.getParcelableExtra("bitmap");
Activity之间的回传数据
1,启动方式:
startActivityForResult(intent, 101);//请求码
2,返回方式:
setResult(100,intent);
finish();//销毁当前界面
3, 回传过来的数据会被 onActivityResult接收
通过请求码和结束码来区分不同请求和回传值

             Intent intent = new Intent(this,SecondActivity.class);
/**
* 带数据
* 1,基本类型和数组
* 2, 传对象 a,bundle对象(andoid写好的)
* b,自定义的对象:序列化  java:Serializable  不可以跨进程  
* android:Parcelable 可以跨进程
* android中推荐使用:Parcelable
*/
/*intent.putExtra("name", "二狗子");//key-value:键值对
intent.putExtra("age", 18);*/

/*Bundle bundle = new Bundle();//袋子
bundle.putString("name","二狗子");
bundle.putInt("age",18);
intent.putExtra("bundle", bundle);*/

/*Student stu = new Student();
stu.setName("二狗子");
stu.setAge(18);
intent.putExtra("stu", stu);//java序列化*/

/*Person  p = new Person("旺财",12);
intent.putExtra("person", p);*/

Bitmap  bitmap =BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
intent.putExtra("bitmap",bitmap);

startActivity(intent);


              

package com.example.kateintent_tz;

import java.io.Serializable;

public class Student implements Serializable{
	private static final long serialVersionUID = 1L;
	
	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;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}

	
}

package com.example.kateintent_tz;

import android.os.Parcel;
import android.os.Parcelable;
/**
 * public class MyParcelable implements Parcelable {
     private int mData;

     public int describeContents() {
         return 0;
     }

     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(mData);
     }

     public static final Parcelable.Creator<MyParcelable> CREATOR
             = new Parcelable.Creator<MyParcelable>() {
         public MyParcelable createFromParcel(Parcel in) {
             return new MyParcelable(in);
         }

         public MyParcelable[] newArray(int size) {
             return new MyParcelable[size];
         }
     };
     
     private MyParcelable(Parcel in) {
         mData = in.readInt();
     }
 }
 * @author Administrator
 *
 */
public class Person implements Parcelable{
	private String name;
	int age;
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
	
	public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel out, int flags) {
    	out.writeString(name);
        out.writeInt(age);
    }

    public static final Parcelable.Creator<Person> CREATOR
            = new Parcelable.Creator<Person>() {
        public Person createFromParcel(Parcel in) {
            return new Person(in);
        }

        public Person[] newArray(int size) {
            return new Person[size];
        }
    };
    
    private Person(Parcel in) {
        name = in.readString();
        age = in.readInt();
    }
	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;
	}
    
}


案例:Activity--启动相册----相册返回图片
 知识:手机中放入(视频 音频  图片 )多媒体文件,android系统会将多媒体文件信息保存到系统数据库中

  



猜你喜欢

转载自blog.csdn.net/taoerit/article/details/79891719