第一章 四大组件

第一章 四大组件

一、四大组件的简单介绍

  • activity负责UI页面跳转代表着一个页面单元。
  • service 负责与UI无关操作,耗时操作(需要再其中另开线程执行耗时操作)
  • Broadcast 各个应用组件中进行通讯,简化通信问题
  • ContentProvider 储存,共享数据,多应用共享

1.Activity的singleInstance启动模式,在同一时刻系统中只存在一个Activity实例

2.Fragment在Android3.0后引入了Fragment,其需要被嵌套在Activity中进行使用,它作为一个更大粒度的UI单元。如果需要在低于android3.0的系统上使用,则需要导入android-support-v4包。

3.Service默认也是执行在UI线程中,所以不要在Service中执行耗时操作除非在其中新建了线程来执行耗时操作。

4.Service中onCreate只会调用一次,当多次调用startService时,onStartCommand会被调用多次,但实际上每个服务都会只存在一个实例,无论调用了多少次startService()方法。

5.当Service运行起来后,需要通过stop-Service()或stopSelf()方法来停止服务,Service不会自动停止。

6.IntentService适用于短期的耗时操作,自带子线程功能,用户只需要重写其内部的onHandlerIntent方法即可,在其中执行耗时操作即可。并且IntentSelf执行完毕后会自动调用stopSelf方法来自我销毁。

7.前台服务的启动方式startForeground(NOTIFY_ID,notifycation);

二、AIDL(接口描述语言)

AIDL就是定义一个接口,客户端(调用端)通过bindService来与远程服务端建立一个连接,在该连接建立时,会返回一个IBinder对象,该对象是服务端Binder的BinderProxy,在建立连接时,客户端通过asInterface方法将该BinderProxy对象包装成本地的Proxy,并将远程调用服务端的BinderProxy对象赋值给Proxy类的mRemote字段,就是通过mRemote来执行远程函数的调用。

代码实例如下:

//调用端
// SsoAuth.aidl
package com.example.zero.testaidl;

interface SsoAuth {
//默认生成的方法
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
        double aDouble, String aString);
//自定义方法
void ssoAuth(String username,String pwd);
}

客户端创建好SsoAuth.aidl后,ReBuild项目,即可自动生成SsoAuth.java文件
其代码如下:

package com.example.zero.testaidl;
// Declare any non-default types here with import statements

public interface SsoAuth extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.example.zero.testaidl.SsoAuth
{
private static final java.lang.String DESCRIPTOR = "com.example.zero.testaidl.SsoAuth";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.example.zero.testaidl.SsoAuth interface,
 * generating a proxy if needed.
 */
public static com.example.zero.testaidl.SsoAuth asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.zero.testaidl.SsoAuth))) {
return ((com.example.zero.testaidl.SsoAuth)iin);
}
return new com.example.zero.testaidl.SsoAuth.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_basicTypes:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
long _arg1;
_arg1 = data.readLong();
boolean _arg2;
_arg2 = (0!=data.readInt());
float _arg3;
_arg3 = data.readFloat();
double _arg4;
_arg4 = data.readDouble();
java.lang.String _arg5;
_arg5 = data.readString();
this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
reply.writeNoException();
return true;
}
case TRANSACTION_ssoAuth:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
java.lang.String _arg1;
_arg1 = data.readString();
this.ssoAuth(_arg0, _arg1);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.example.zero.testaidl.SsoAuth
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
/**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
@Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(anInt);
_data.writeLong(aLong);
_data.writeInt(((aBoolean)?(1):(0)));
_data.writeFloat(aFloat);
_data.writeDouble(aDouble);
_data.writeString(aString);
mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public void ssoAuth(java.lang.String username, java.lang.String pwd) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(username);
_data.writeString(pwd);
mRemote.transact(Stub.TRANSACTION_ssoAuth, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_ssoAuth = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
/**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;
public void ssoAuth(java.lang.String username, java.lang.String pwd) throws android.os.RemoteException;
}

将客户端的aidl文件夹拷贝到被服务端(被调用端),服务端与客户端的aidl的包名,类名完全一致,生成的aidl也完全一致,所以Rebuild服务端后也会生成相同的SsoAuth.java文件
客户端通过Service(Service是一个外壳,包含着Stub的子类,在onBind方法中返回子类对象)进行调用:

public class SinaSsoAuthService extends Service {

SinaSsoImpl mBinder = new SinaSsoImpl();

@Override
public void onCreate() {
    super.onCreate();
    Log.d(this.getClass().getSimpleName(), "---onCreate");
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
    Log.d(this.getClass().getSimpleName(), "---onBind");
    return mBinder;
}


class SinaSsoImpl extends SsoAuth.Stub {

    @Override
    public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }

    @Override
    public void ssoAuth(String username, String pwd) throws RemoteException {
        Log.d("mjc", "这里是新浪微博,用户名:" + username + ",密码:" + pwd);
        }
    }
}

需要在Manifest中对Service进行注册,重要的是意图过滤器的书写:

<intent-filter>
<action android:name="com.example.zero.testaidlservice.SinaSsoAuthService"/>
</intent-filter>

在客户端完成调用服务端的代码:

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

public void initWidgets() {
    btnStart = (Button) findViewById(R.id.btnStart);
    btnStart.setOnClickListener(this);
}

@Override
public void onClick(View v) {
    if (ssoAuth == null) {
        bindSsoService();
    } else {
        doSsoAuth();
    }
}

private void bindSsoService() {
    Intent intent = new Intent();
    intent.setAction("com.example.zero.testaidlservice.SinaSsoAuthService");
    intent.setPackage("com.example.zero.testaidlservice");
    bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}


ServiceConnection serviceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        try{
            ssoAuth = SsoAuth.Stub.asInterface(service);
            doSsoAuth();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        ssoAuth = null;
    }
};

private void doSsoAuth() {
    try {
        ssoAuth.ssoAuth("Mr.ma", "123321");
    } catch (RemoteException e) {
        e.printStackTrace();
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    unbindService(serviceConnection);
}

这一切的核心都是AIDL中生成的Stub类及其背后的Binder机制。

Proxy模式暂时不了解,所以对于自动生成的SsoAuth.java文件不做详细分析,同时其中使用了Parcel,也应该了解下其用法。有待补充。

三、Broadcast

1.分类
  • 普通广播:执行顺序不确定,接收者之间不能传递处理结果,中途不能停止传播,直到没有接收器时才能停止广播,传播效率比较高。
  • 有序广播:sendOrderBroadcast()方法来发送有序广播。有序广播的优先级可以通过receiver中的android:priority属性来设定,数值越大,越优先接受到广播,有序广播可以在中途停止(不在向下进行传递广播),方法为abrotBroadcast();可通过setResultData(String data)和setResultExtras(Bundle extras)方法来向下一级传递数据,相应的下一级接收器通过getResultData()及getResultExtras(boolean makeMap)来获取上一级传递来的数据。
  • 本地广播:在21版的v4包中新增了本地广播,之前所有的广播都是所有应用都可以接收到的,肯呢个存在安全隐患,(虽然在设定intent-filter 中的action时都使用了公司的域名等级制)。具体方法:

  • sticky广播:发送广播后,一直滞留(同一时刻仅能有一条广播存在),当已经存在一条,再次发送新的一条时,应该先调用removeStickyBroadcast()再发送。发送方法:sendStickyBroadcast()。sticky广播需要权限android.permission.BROADCAST_STYCKY

2. 广播的注册方式

①静态注册,在AndroidManifest.xml文件中进行注册
②动态注册
registerReceiver(new TestReceiver(),strAction);

//发送广播时
sendBroadcast(new Intent(strAction));

//动态注册时,需要动态销毁广播。
@Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(netWorkChangeReceiver);
    }

3.本地广播的相关方法

“`
Public Methods

static LocalBroadcastManager getInstance(Context context)

void registerReceiver(BroadcastReceiver receiver, IntentFilter filter)

boolean sendBroadcast(Intent intent)

void sendBroadcastSync(Intent intent)

void unregisterReceiver(BroadcastReceiver receiver)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值