天天看点

Android四大组件的学习与理解之(Activity组件与Service组件)Android四大组件

Android四大组件

Activities 描述UI,并且处理用户与机器屏幕的交互。 

是用户操作的可视化界面;它为用户提供了一个完成操作指令的窗口。当我们创建完毕Activity之后,需要调用setContentView()方法来完成界面的显示;以此来为用户提供交互的入口。在Android App 中只要能看见的几乎都要依托于Activity,所以Activity是在开发中使用最频繁的一种组件。

Services 处理与应用程序关联的后台操作。 

Broadcast Receivers 处理Android操作系统和应用程序之间的通信。 

Content Providers 处理数据和数据库管理方面的问题。

附件组件:

Fragments 代表活动中的一个行为或者一部分用户界面。

Views 绘制在屏幕上的UI元素,包括按钮,列表等。

Layouts 控制屏幕格式,展示视图外观的View的继承。

Intents 组件间的消息连线。

Resources 外部元素,例如字符串资源、常量资源及图片资源等。

Manifest 应用程序的配置文件。

关于四大组件:

Activity组件

Activity的生命周期

1、概念:Activity是一种展示型组件,主要是向用户展示一个界面,并且可以接收用户的输入信息从而和用户进行交互。对用户来说,Activity就是Android应用的全部,因为其他三大组件对用户来说是不可感知的。

在Android中会维持一个Activity Stack(Activity栈),当一个新的Activity创建时,他就会放到

栈顶,这个Activity就处于运行状态,当再有一个新的Activity被创建后,会重新压入栈顶,而之前的那个

Activity会在这个Activity之下,就像子弹压入弹匣一样,之前的Activity就会进入后台

一个avtivity实际上有四种状态:

1.运行中(running):这时Activity位于栈顶,是可见的,可与用户交互的,

2.暂停(Paused):当Activity失去焦点,不能跟用户交互了,但依然可见,就处于暂停状态,当一个全新的非全屏的

Activity或者一个透明的Activity放到栈顶,activity就处于暂停状态,这个时候的Activity各种数据还保留着,

只有内存极低的情况下,Activity才会被删除

3.停止(Stoped):当一个Activity被另一个Activity完全覆盖,或者点击HOME键退出了后台,这个Activity

就处于停止状态,这里有些是跟暂停状态相似的,这个时候Activity的各种数据保留着,当系统别的地方需要用到

数据时,系统会自动的去销毁Activity

4.销毁(Detroyed):当我们点击返回键或者系统在内存不够用的情况下就会把Activity从栈中移除出来进行销毁

被系统回收,这时Activity处于销毁状态

Android四大组件的学习与理解之(Activity组件与Service组件)Android四大组件

##

Activity中所有的组件都要显示的配置

其中:

name:指定Activity实现类的类名

icon:指定该Activity所对应的图标

label:指定该Activity所对应的标签

exported:指定该Activity对否可以被其他应用调用,如果设为true,那么该activity讲可以被其他应用调用

launchMode:指定Activity的加载模式(四种,下面)

Activity的四种加载模式:

standard

singleTop

singleTask

singleInstance

Standard:默认模式,不用写配置,允许多个相同的实例,也允许多个Activity叠加

SingleTop:允许多个相同的实例,但不允许Activity叠加,只允许其他Activity调用onnewIntent()方法创建新的Activity

SingTask:只允许有一个实例的Activity,如果在同意个task中有多个相同的Activity,则最后启动的Activity会自动Destroy前面的Activity

SingleInstance:只有一个实例,且一个task中只允许有这一个Activity存在,若有其他的Activity,则重新开启一个task。

Android四大组件的学习与理解之(Activity组件与Service组件)Android四大组件

Activity之间的跳转:

(1)显式跳转

首先创建一个Intent对象,调用Intent的构造方法,传入两个参数,第一个参数

Context要求传入一个上下文,第二个参数Class指定要启动的目标活动;然后调用startActivity()方法传入Intent对象就可以启动目标活动了。

Android四大组件的学习与理解之(Activity组件与Service组件)Android四大组件

(2)隐式跳转

首先在AndroidManifest.xml中配置action以及category;

Android四大组件的学习与理解之(Activity组件与Service组件)Android四大组件

然后在activity中创建一个Intent对象,调用构造方法,传入action配置的字符串,再调用addCategory()方法添加category字符串;最后调用startActivity()方法传入Intent对象就可以启动目标活动了,只有和设置的action以及category完全匹配的目标活动才会被启动。

Android四大组件的学习与理解之(Activity组件与Service组件)Android四大组件

Service组件:

服务(Service)是Android中实现程序后台运行的解决方案,它非常适合去执行那些不需要和用户交互而且还要求长期运行的任务。服务的运行不依赖于任何用户界面,即使程序被切换到后台,或者用户打开了另外一个应用程序,服务仍然能够保持正常运行。

不过需要注意的是,服务并不是运行在一个独立的进程当中的,而是依赖于创建服务时所在的应用程序进程。与某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行。另外.也不要被服务的后台概念所迷惑,实际上服务并不会自动开启线程,所有的代码都是默认运行在主线程当中的。也就是说,我们需要在服务的内部手动创建子线程,并在这里执行具体的任务,否则就有可能出现主线程被阻塞住的情况。

1.startService和bindService的区别:

startService只是启动Service,启动它的组件(如Activity)和Service并没有关联,只有当Service调用stopSelf或者其他组件调用stopService服务才会终止。

bindService方法启动Service,其他组件可以通过回调获取Service的代理对象和Service交互,而这两方也进行了绑定,当启动方销毁时,Service也会自动进行unBind操作,当发现所有绑定都进行了unBind时才会销毁Service。

2.IntentService

IntentService相比父类Service而言,其最大特点是其回调函数Onhandleintent中可以直接进行耗时操作,不必再开线程,其原理是IntentService的成员变量,Handler在初始化时已经属于工作流程,之后HandleMessage,包括onHandleIntent等函数都运行在工作线程中

3.Service工作流程:

onCreate():当Service第一次被创建后立即回调该方法,该方法在整个生命周期 中只会调用一次!

onDestory():当Service被关闭时会回调该方法,该方法只会回调一次!

onStartCommand(intent,flag,startId):早期版本是onStart(intent,startId), 当客户端调用startService(Intent)方法时会回调,可多次调用StartService方法, 但不会再创建新的Service对象,而是继续复用前面产生的Service对象,但会继续回调 onStartCommand()方法!

IBinder onOnbind(intent):该方法是Service都必须实现的方法,该方法会返回一个 IBinder对象,app通过该对象与Service组件进行通信!

onUnbind(intent):当该Service上绑定的所有客户端都断开时会回调该方法!

测试Service的工作流程:

1.创建Service

public class TestService extends Service {
    private String TAG = "TestService";

    //必须要实现的方法
    @Override
    public IBinder onBind(Intent intent){
        Log.i(TAG,"onBind方法被调用!");
        return null;
    }


    //Service被创建时调用
    @Override
    public void onCreate(){
        Log.d(TAG, "onCreate: onCreate方法被调用");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent,int flags,int startId){

        Log.i(TAG, "onStartCommand: onStartConmmand方法被调用");
        return super.onStartCommand(intent,flags,startId);
    }

    @Override
    public void onDestroy(){
        Log.i(TAG, "onDestroy: onDestroy方法被调用");
        super.onDestroy();
    }
}
           

重写Service的 onCreate()、onStartCommand()和onDestory()方法。其中 onCreate() 方法在服务创建的时候调用,onStartCommand() 方法会在每次服务启动的时候调用,onDestory()方法会在服务销毁的时候调用。

通常情况下,如果我们希望服务一旦启动就立刻去执行任务,就可以将逻辑写在onStartCommand() 方法里。

2.在AndroidMainFest.xml中声明Service。所有组件都要显示的声明

<service android:name=".TestService">
            <intent-filter>
                <action android:name="com.example.demoapplication.service.TEST_SERVICE"/>
            </intent-filter>
        </service>
           

3.UI界面中添加两个按钮,ID为stsart_btn,end_btn

MainActivity中的代码

public class MainActivity extends AppCompatActivity {


    private Button start;
    private Button end;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        start = (Button) findViewById(R.id.start_btn);
        end =  (Button) findViewById(R.id.end_btn);

        //创建启动Service时的Intent,以及Intent属性
        final Intent intent = new Intent(this,TestService.class);  //Android5.0以后版本
        /*final Intent intent = new Intent();  Android5.0以前版本*/
        intent.setAction("com.example.demoapplication.service.TEST_SERVICE");

        //为两个按钮设置单击事件,分别是start和end
        start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startService(intent);
            }
        });

        end.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopService(intent);
            }
        });
    }
}
           

使用前台服务

前台服务与普通服务的最大区别在于,它会一直有一个正在运行的图标在系统的状态栏中,下拉状态栏后可以看到更加详细的内容,非常类似于通知的效果。

@Override

public void onCreate(){

super.onCreate();

Log.d("MyService","onCreate executed");

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

PendingIntent pi = PendingIntent.getActivity(this,0,intent,0);

Notification notification = new NotificationCompat.Builder(this)

.setContentTitle("This is content title")

.setContentText("This is content text")

.setWhen(System.currentTimeMillis())

.setSmallIcon(R.mipmap.ic_launcher)

.setLargeIcon(BitmapFactory.decodeResource(getResources(),

R.mipmap.ic_launcher))

.setContentIntent(pi)

.build();

startForeground(1,notification);

}

这里只修改了onCreate()方法中的代码,构造一个Notification对象后并没有使用NotificationManager 来将通知显示出来,而是调用了startForeground()方法,该方法会将MyService变成一个前台服务,并在系统状态栏中显示出来。

Activity和Service通信

他们之间交流的媒介就是Service中的onBind()方法,返回一个我们自定义的binder对象

基本流程如下:

1. 自定义service中。自定义一个Bind类,然后将需要暴露的方法写到该类中

2.Service类中,实例化这个自定义Binder类,然后重写onBind()方法,将这个Binder对象返回!

3.Activity类中实例化一个ServiceConnection对象,重写onServiceConnected()方法,然后 获取Binder对象,然后调用相关方法即可!

Binder机制初涉:

IBinder是Android给我们提供的一个进程间通信的一个接口,而我们一般是不直接实现这个接口的,而是通过继承Binder来实现进程间通信,是Android中实现IPC(进程间通信)的一种方式

Binder机制由一系列系统组件构成,Client,server ,Service Manager 和Binder驱动程序

Bind的调用流程如下

1.Client调用某个代理接口中的方法时,代理接口的方法会将Client传递的参数打包成Parcel对象

2.然后代理接口把该Parcel对象发送给内核中的Binder Driver

3.然后Server会读取Binder Driver中的请求数据,假如是发送给自己的,解包Parcel对象,处理并将结果返回

Binder机制具有可靠性,传输性能,安全性

AIDL:

跨进程通信,因为在Android系统中,个个应用程序都运行在自己的进程中,进程之间一般是无法进行数据交换的,而为了实现跨进程,Android给我们提供了上面说的Binder机制,而这个机制使用的接口语言就是AIDL(Android Intereface Definition Language)

AIDL注意事项:

接口名词需要于aidl文件名相同

接口和方法前面不要家访问权限修饰符“public,private,protected等,也不能用static final等

AIDL默认支持的类型包括Java基本类型,String,List,Map,CharSqquence,除此之外的其他类型都需要import声明,对于使用自定义类型作为参数或者返回值,自定义类型需要实现Parcelable接口,

自定义类型和AIDL生成的其他接口类型在aidl描述文件中,应该显示import,即便在该类和定义的包在同一个包中