Android四大组件之Activity:定义,Intent意图,IntentFilter意图过滤器,Activity启动流程,状态和回调,加载模式launchMode,查看应用action

Activity定义

Activity, 直译为活动, 它是Android定义的四大应用组件之一,也是最重要用得最多的
用来提供一个能让用户操作并与之交互的界面
一个应用有多个界面, 也就是包含多个Activity
打电话,发短信, 拍照,发邮件等功能都是通过Activity来做的

组件的特点

它的类必须实现特定接口或继承特定类

需要在配置文件中配置其全类名

它的对象不是通过new来创建的, 而是系统自动创建的

它的对象具有一定的生命周期, 它的类中有对应的生命周期回调方法
比如我们之前学习的网页开发中的Servlet接口就是组件的接口
Servlet是一个interface, 我们的Servlet类都必须是此接口的实现类,是一种服务器端的组件, 用来处理 客户端(浏览器)提交的请求, 并返回一个响应界面
两个进行对比:

Servlet Activity
组件 服务器端组件 Android客户端组件
接口 Servlet接口 Activity类
注册 web.xml AndroidManifest.xml
发出的请求源 浏览器 手机屏幕

Intent

这个不是Android中的四大应用组件之一,但是和Activity相关性很大
Intent, 直译为意图, 也就是你想要做什么或想要去哪?
Intent是Activity, Service和BroadcastReceiver这三个应用组件之间进行通信的信使,
例如: 我要在Activity中启动另一个Actvity, 就必须使用Intent对象
意图对象还可以携带数据

Intent的分类

显示意图 :
明确指定的目标组件的意图,比如其他应用要明确打开微信
创建对象 : Intent(Context context, Class clazz)
何时使用 : 当操作当前自己应用的组件时使用

隐式意图 :
没有明确指定目标组件的意图,
比如图片要分享,但是分享的路径有很多,比如分享到微信,邮件…
创建对象 : Intent(String action)
何时使用 : 当操作其它应用的组件时使用

IntentFilter(意图过滤器)

这个就是上面不是有一个意图吗?就是想跳转到其他的Activity,但是手机这么知道跳转到哪一个呢?那就是意图过滤器起作用了.
就好像我们之前学习的Servlet,每一个请求(对应这里的意图)都要首先和< url-pattern>(对应这里的意图过滤器)就行匹配,如果匹配成功,就给< url-pattern>对应的servlet进行处理

在配置Activity时, 可以为Activity指定一个IntentFilter的配置
如果你的Activity希望其它应用能访问到, 需要配置< intent-filter>
如果你想启动其它应用的界面你必须用隐式intent, 且目标界面Activty配置了< intent-filter>
比如想让这个activity成为应用的第一个活动,就设置

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

对应的常见API

Activity: 活动
      startActivity(Intent intent): 一般启动Activity
      startActivityForResult(int reqCode, Intent intent): 带回调启动Activity
      onActivityResult(int reqCode, int resultCode, Intent data): 回调方法
      setResult(int resultCode, Intent data): 设置要返回的结果
      finish(): 结束当前Activity
      getIntent(): 得到启动Activity的意图
Intent: 意图
      Intent(Context packageContext, Class<?> cls) :  用于创建显示意图对象
      Intent(String action): 用于创建隐式意图对象
      putExtra(String name, Xxx value): 保存额外数据
      Xxx getXxxExtra(String name): 获取额外数据
      setData(Uri data): 设置有特定格式的uri数据
View: 代表视图的根基类
      setOnClickListener(OnClickListener listener): 设置点击监听
      setOnLongClickListener(OnLongListener listener): 设置长按监听
Activity生命周期相关方法
      onCreate()
      onStart()
      onResume()
      onPause()
      onRestart()
      onStop()
      onDestory()
设置点击监听的2种方式     
方式一:  Activity中添加监听:  
	view.setOnClickListener(OnClickListener listener);
方式二:  布局添加监听:  
	layout中:   android:onclick=“方法名”
	Activity中: public void 方法名(View v) {
    
       }

设置长按监听 
view.setOnLongClickListener(OnLongClickListener listener)

利用到反射技术的

1.就比如之前使用过的意图(显式的)它创建对象时候是使用Intent(Context context,Class c)
2.比如之前的布局文件,之前只是写一个名字Button就知道要创建Button对象,也是通过反射的
3.功能清单文件中,包名不用写,也是通过反射技术的

应用上面的例子

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.hello"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="9"
        android:targetSdkVersion="9" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
        </activity>
        <activity 
            android:name=".Message"
            android:label="@string/title_activity_message" >
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>           
        </activity>
        <activity
            android:name=".Message2"
            android:label="@string/title_activity_message2" >
        </activity>
    </application>

</manifest>

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <EditText
            android:id="@+id/editTextMessage"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10" 
            android:hint="携带的信息"
            >

            <requestFocus />
        </EditText>

    </LinearLayout>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="返回" 
        android:onClick="back1"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="带结果返回" 
        android:onClick="back2"/>

</LinearLayout>

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <EditText
            android:id="@+id/editText1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10" 
            android:hint="需要携带的信息"
            >

            <requestFocus />
        </EditText>

    </LinearLayout>

    <Button
        android:id="@+id/Button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="一般启动" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="回调启动" />

</LinearLayout>

package com.example.hello;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class Message extends Activity implements OnClickListener
{
    
    
	/*
	 * 步骤:
	 * 1.建好界面布局
	 * 2.实现Activity的功能:
	 * 		1)定义所有的需要操作的视图对象并且初始化
	 * 		2)设置监听事件,实现回调逻辑
	 * 3.实现一般的跳转
	 * 		1)定义好第二个的界面
	 * 			1)布局
	 * 			2)定义Activity类
	 * 			3)在功能清单配置好
	 * 			4)重写onCreate方法
	 * 		2)启动界面二
	 * 			1)创建显式的Intent对象
	 * 			2)通过Intent对象携带额外数据
	 * 			3)启动Activity
	 * 			4)在另外一个界面得到Intent对象
	 * 			5)读取到数据后显示出来
	 */
	private EditText editText1;
	private Button Button1;
	private Button Button2;
	
	
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
    
    
		super.onCreate(savedInstanceState);
		setContentView(R.layout.message);
		//初始化视图对象
		editText1=(EditText) findViewById(R.id.editText1);
		Button1=(Button) findViewById(R.id.Button1);
		Button2=(Button) findViewById(R.id.button2);
		
		//设置监听事件
		Button1.setOnClickListener(this);
		Button2.setOnClickListener(this);
	}


	@Override
	public void onClick(View v)
	{
    
    
		if(v==Button1)
		{
    
    
			Toast.makeText(this, "一般启动", 0).show();
			//创建对象
			Intent intent = new Intent(this, Message2.class);
			//携带数据
			intent.putExtra("message", editText1.getText().toString());
			//启动Activity
			startActivity(intent);
		}
		else if(v==Button2)
		{
    
    
			Toast.makeText(this, "回调启动", 0).show();
			//创建对象
			Intent intent = new Intent(this, Message2.class);
			//携带数据
			intent.putExtra("message", editText1.getText().toString());
			//带回调启动Activity
			int requestCode=1;
			startActivityForResult(intent, requestCode);
		}
	}
	//带结果的返回是父类的方法,只需要重写就行
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data)
	{
    
    
		super.onActivityResult(requestCode, resultCode, data);
		if(requestCode==1&&resultCode==2)
		{
    
    
			String string = data.getStringExtra("result").toString();
			editText1.setText(string);
		}
	}
}

package com.example.hello;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;

public class Message2 extends Activity
{
    
    
	private EditText edittext;
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
    
    
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_message2);
		
		edittext=(EditText) findViewById(R.id.editTextMessage);
		Intent intent = getIntent();
		edittext.setText(intent.getStringExtra("message"));
		
	}
	//使用的是另外一种方法添加监听
	public void back1(View v)
	{
    
    
		finish();
	}
	public void back2(View v)
	{
    
    
		//在关闭之前先准备好要返回的值,然后将它设置好就关闭当前Activity
		int resultCode=2;
		Intent data=new Intent();
		data.putExtra("result", edittext.getText().toString());
		setResult(resultCode, data);
		finish();
	}

}

启动一个Activity的流程

在这里插入图片描述

Activity界面的四种状态和回调方法

四种状态

运行状态: 可见也可操作

暂停状态: 可见但不可操作,就比如在当前窗口有一个警告的窗口弹出来,
当前窗口还能看到,但是操作不了当前窗口,只能操作那个警告的窗口

停止状态: 不可见,但对象存在,就比如按了home键返回桌面

死亡状态: 对象不存在

回调方法

onCreate()
onStart()
onResume()
onPause()
onRestart()
onStop()
onDestory()

在这里插入图片描述

Activity的加载模式(launchMode)

在Android中, 启动一个Activity有时需要总是创建一个新对象, 有时需要复用已有的对象, 
可以通过在配置activity时通过launchMode属性指定
下面以三个Activity来说明,分别是1,2,3这三个Activity,它们之间都可以互相调用
launchMode属性值(4):

standard: 
标准模式,每次调用startActivity()方法就会产生一个新的实例。
1调用2就会产生2对象放在栈顶,然后
2调用1也会重新产生一个1对象放在栈顶,然后
1调用1自己也会产生一个新的1的对象放在栈顶
栈的对象有1-2-1-1

singleTop: 
如果已经有一个实例位于Activity栈的顶部时,就不产生新的实例;如果不位于栈顶,会产生一个新的实例。
1调用1就什么也没有产生,栈顶只有1自己,然后
1调用2就会产生2对象放在栈顶,然后
2调用1也会重新产生一个1对象放在栈顶,然后
栈的对象有1-2-1

singleTask: 
只有一个实例, 默认在当前Task中
1调用1就什么也没有产生,栈顶只有1自己,然后
1调用2就会产生2对象放在栈顶,然后
2调用1也会销毁2,暴露1出来给你看,然后
栈的对象有1,因为2已经销毁了

singleInstance: 
只有一个实例, 创建时会新建一个栈, 且此栈中不能有其它对象
这个特殊时候还是挺好用的
例如给2设置singleInstance,其他的不设置
1调用2,就会产生新的一个栈并且放在第一个栈(当前栈)的前面
现在就是显示2
2调用3,那么3就会在第一个栈的栈顶创建,
现在显示的是第一个栈的栈顶的3
现在第一个栈在新建的栈的前面
现在销毁3,显示的是1
销毁1,现在才显示2
这里和平常的顺序不一样

如何找某个应用的action

现在以Phone为例
先是让手机模拟器处于桌面,
新建一个LogCat的过滤器,过滤出来Tag是ActivityManager的输出内容
然后点击手机模拟器的电话应用
LogCat的内容是
在这里插入图片描述
里面的ActivityManager跟你说启动一个com.android.dialer/.DialtactsActivity
现在我们知道启动的是DialtactsActivity这样一个类,
然后去到Android的原码进行查找是哪一个应用的
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
然后找到这个应用的清单文件
在这里插入图片描述
从里面找DialtactsActivity就可以找到对应的action,就是对应的android.intent.action.DIAL,这不就好起来了吗?
在这里插入图片描述

例子

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.hello"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="9"
        android:targetSdkVersion="9" />
    <!-- 打开打电话的权限 -->
    <uses-permission android:name="android.permission.CALL_PHONE"/>
    <!-- 打开发短信的权限 -->
    <uses-permission android:name="android.permission.SEND_SMS"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
        </activity>
        <activity
            android:name=".Message"
            android:label="@string/title_activity_message" >
            >
        


        </activity>
        <activity
            android:name=".Message2"
            android:label="@string/title_activity_message2" >
        </activity>
        <activity
            android:name=".First"
            android:label="@string/title_activity_first" >
        </activity>
        <activity
            android:name=".Second"
            android:label="@string/title_activity_second" >
        </activity>
        <activity
            android:name=".Third"
            android:label="@string/title_activity_third" >
        </activity>
        <activity
            android:name=".Phone"
            android:label="@string/title_activity_phone" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="电话号码: " />

        <EditText
            android:id="@+id/editTextPhone"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:ems="10" >

            <requestFocus />
        </EditText>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="短信内容: " />

        <EditText
            android:id="@+id/editTextMessage"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:ems="10" >

            <requestFocus />
        </EditText>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <Button
            android:id="@+id/call"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="打电话" />

        <Button
            android:id="@+id/send"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="发短信" />
    </LinearLayout>

</LinearLayout>
package com.example.hello;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class Phone extends Activity implements OnLongClickListener
{
    
    
	private EditText editTextPhone;
	private EditText editTextMessage;
	private Button call;
	private Button send;
	private OnClickListener onClickListener=new OnClickListener()
	{
    
    

		@Override
		public void onClick(View v)
		{
    
    
			if(v==call)
			{
    
    
				Toast.makeText(Phone.this, "点击打电话", 0).show();
				/*
				 * 创建一个Intent(隐式),因为是不同的应用之间的调用了
				 * 10-03 09:07:04.041: I/ActivityManager(387): Displayed com.android.dialer/.DialtactsActivity: +1s254ms
				 *  <action android:name="android.intent.action.DIAL" />
				 */
				String action="android.intent.action.DIAL";
				action=Intent.ACTION_DIAL;//值和上面是一样的
				Intent intent=new Intent(action);
				
				//设置携带的数据,因为电话应用数据有约束<data android:scheme="tel" />,所以使用setData的方式
				String number = editTextPhone.getText().toString();
				intent.setData(Uri.parse("tel:"+number));
				
				startActivity(intent);
			}
			else if(v==send)
			{
    
    
				Toast.makeText(Phone.this, "点击发短信", 0).show();
				String action=Intent.ACTION_SENDTO;
				Intent intent=new Intent(action);
				String number=editTextPhone.getText().toString();
				intent.setData(Uri.parse("smsto:"+number));
				String sms=editTextMessage.getText().toString();
				intent.putExtra("sms_body", sms);
				startActivity(intent);
			}
		}
	};
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
    
    
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_phone);
		
		editTextPhone=(EditText) findViewById(R.id.editTextPhone);
		editTextMessage=(EditText) findViewById(R.id.editTextMessage);
		call=(Button) findViewById(R.id.call);
		send=(Button) findViewById(R.id.send);
		
		//新的方法,设置成员变量进去的
		call.setOnClickListener(onClickListener);
		send.setOnClickListener(onClickListener);
		
		call.setOnLongClickListener(this);
		send.setOnLongClickListener(this);
	}
	@Override
	public boolean onLongClick(View v)
	{
    
    
		if(v==call)
		{
    
    
			Toast.makeText(Phone.this, "长按打电话", 0).show();
			
			/*
			 * 和上面的点击一样的,就是action不一样
			 * 只不过你会遇到权限的问题,需要给这个应用打电话的权限
			 * 在功能清单文件里面配置
			 *     	<!-- 打开打电话的权限 -->
    		 *		<uses-permission android:name="android.permission.CALL_PHONE"/>
    		 *	或者直接在功能清单文件的下面找到permissions按钮,在里面找到你需要的
    		 *	权限,然后直接添加,然后软件就会帮你生成对应的代码
			 */
			String action=Intent.ACTION_CALL;
			Intent intent=new Intent(action);
			intent.setData(Uri.parse("tel:"+editTextPhone.getText().toString()));
			startActivity(intent);
		}
		else if(v==send)
		{
    
    
			Toast.makeText(Phone.this, "长按发短信", 0).show();
			SmsManager smsManager=SmsManager.getDefault();
			
			String number=editTextPhone.getText().toString();
			String text=editTextMessage.getText().toString();
			/*
			 * * @param destinationAddress the address to send the message to
			 * 这个destinationAddress就是电话号码
			 * 
			 * * @param scAddress is the service center address or null to use
			 *  the current default SMSC
			 *  scAddress就是服务中心的地址,没有就默认
			 *  
			 *  @param text the body of the message to send
			 *  text是短信的内容
			 *  
			 *  sentIntent if not NULL this <code>PendingIntent</code> is
		     *  broadcast when the message is successfully sent, or failed.
		     *  The result code will be <code>Activity.RESULT_OK</code> for success,
		     *  后面两个就是短息发送成功和阅读成功的回执
			 */
			smsManager.sendTextMessage(number, null, text, null, null);
		}

		return true;//返回true,不会再触发点击事件,代表此事件已经被消费了
	}
}

猜你喜欢

转载自blog.csdn.net/qq_43416157/article/details/108902162