Android开发基础-四大组件之Broadcast

一、广播机制的作用

广播的主要作用是用于通知。如果在应用内,我们常用的通知方式是回调和广播。这两者之前,回调的速度快,保障性高,而广播则简单,但是速度没有回调高。什么情况下使用广播呢?当有多个地方等待通知的时候,可以使用广播。原理上广播和回调差不多的,广播的原理就是使用Binder机制,把action注册到ActivityManagerService里头,然后广播的时候,就去里面寻找符合规则的,再调用onReceive这个方法。
另外一种情况就是跨进程通讯,当然还有AIDL,这里的话是广播。广播是可以跨应用通知的,比如我们接收系统的广播!也可以进行权限的控制,谁可以接收到这样的广播。

广播分为广播发送者和广播接收者。

二、广播接收者

这里先以监视电量变化的广播为例来说明如何创建一个广播接收者。
1.创建一个BroadcastReceiver的子类,重写其onReceive方法。

public class BatteryStatusReceiver extends BroadcastReceiver {
    private static final String TAG = "BatteryStatusReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.d(TAG, "action is == " + action);
        if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
            Log.d(TAG, "电量改变了的广播...");
        } else if (action.equals(Intent.ACTION_BATTERY_LOW)) {
            Log.d(TAG, "电池低电量广播...");
        } else if (action.equals(Intent.ACTION_BATTERY_OKAY)) {
            Log.d(TAG, "电池充电完成。...");
        }
    }
}

2.添加权限


3.注册该广播接收者,这里采用在MainActivity里动态注册的方式。关于动态注册和静态注册后面再说明。

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    private BatteryStatusReceiver mReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        IntentFilter intentFilter = new IntentFilter();
        //设置频道,也就是设置要监听的广播action.
        intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
        intentFilter.addAction(Intent.ACTION_BATTERY_OKAY);
        intentFilter.addAction(Intent.ACTION_BATTERY_LOW);
        mReceiver = new BatteryStatusReceiver();
        //注册广播
        registerReceiver(mReceiver, intentFilter);
        Log.d(TAG, "register receive..");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //取消广播注册,释放资源
        if (mReceiver != null) {
            unregisterReceiver(mReceiver);
            mReceiver = null;
            Log.d(TAG, "unregister receive..");
        }
    }
}

三、广播发送者

这里又分为无序广播和有序广播。

1.无序广播

public void sendBroadcast(View view) {
        Intent intent = new Intent();
        //action只能有一个,所以叫setAction而不是addActon。
        //而广播接收者可以监听多个广播,所以是addAction
        //action的命名一般是包名+动作名,这样子比较唯一
        intent.setAction("com.sunofbeaches.broadcastdemo.SEND_BROADCAST_CLICK");
        //也可以携带数据
        intent.putExtra("Content", "这是我点击按钮发送的广播!");
        sendBroadcast(intent);
    }

这里我们演示怎么使用一个内部类来接收广播。内部广播接收者类,需要是静态的,Public的,注册的时候,是外部类名$内部类名。

public static class InnerReceiver extends BroadcastReceiver{

        private static final String TAG = "InnerReceiver";

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Log.d(TAG, "Inner receiver 接收到的actions... " + action);
            if ("com.sunofbeaches.broadcastdemo.SEND_BROADCAST_CLICK".equals(action)) {
                String content = intent.getStringExtra("Content");
                Log.d(TAG, "content is == " + content);
            }
        }
    }

静态注册的代码:

        
            
                
            
        

2.有序广播

有序广播就类似于单位的通知,由上级一级一级往下传。特点是:
1.有序
2.可以终止往下传达
3.可以修改广播的内容
发送有序广播的API是sendOrderedBroadcast

@Override
public void sendOrderedBroadcast(
    Intent intent, String receiverPermission, BroadcastReceiver resultReceiver,
    Handler scheduler, int initialCode, String initialData,
    Bundle initialExtras) {
    mBase.sendOrderedBroadcast(intent, receiverPermission,
            resultReceiver, scheduler, initialCode,
            initialData, initialExtras);
}

第一个参数,不用说了,我们发送广播就知道了,这个是意图对象,用于封装数据和设置过滤。
第二个参数是权限,权限我们后面会详细说到,虽然很少用到,但是你知道这个思想,有利于你以后自己钻研android的代码。
第三个参数是广播接收者,这个广播接收者是最终接收的广播接收者,用于检查数据是否有传达或者数据被修改。
第四个参数是一个自定义的Hanlder,用于处理结果接收者,也就是上面那个接收者的回调。
第五个参数是初始码,这个会作为结果码,通常是Activity.RESULT_OK,也就是-1。
第六个参数是用于传递数据的,这个数据在各个Receiver里获取到,通过getResultData方法获取。这个其实通常为null。
第七个参数也是用于封装数据的,不同的是,这个用于封装数据集合。
以下是原api的说明文档:


sendOrderedBroadcast

下面以xxx基金会向贫困生发资助金为例来说明有序广播的特点:
广播发送方代码:

public void sendDonation(View view) {
        Intent intent = new Intent();
        intent.setAction("com.sunofbeaches.broadcastdemo.DONATION");
        Bundle bundle = new Bundle();
        bundle.putInt("money", 1000 * 500);
        sendOrderedBroadcast(intent, null, null, null, 1, "给每个贫困的学生资助1000元", bundle);
    }

四个接收者的代码如下,分别是学校接收者,年级接收者,班级接收者,贫困这生接收者!
学校广播接收者:

public class SchoolReceiver extends BroadcastReceiver {
    private static final String TAG = "SchoolReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle resultExtras = getResultExtras(true);
        int money = resultExtras.getInt("money");
        //学校处理一下,分给5个年级
        int perGrade = money / 5;
        Log.d(TAG, "学校接收到捐款--> " + money);
        Bundle bundle = new Bundle();
        bundle.putInt("money", perGrade);
        setResultExtras(bundle);
    }
}

年级广播接收者:

public class GradeReceiver extends BroadcastReceiver {
    private static final String TAG = "GradeReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle resultExtras = getResultExtras(true);
        //假设每个年级有10个班
        Log.d(TAG, "年级收到捐款--> " + resultExtras.getInt("money"));
        resultExtras.putInt("money", resultExtras.getInt("money") / 10);
    }
}

班级广播接收者:

public class ClassReceiver extends BroadcastReceiver {
    private static final String TAG = "ClassReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle resultExtras = getResultExtras(true);
        //假设每个班有10个贫困的孩子
        int perStudent = resultExtras.getInt("money")/10;
        Log.d(TAG, "班级收到捐款--> " + resultExtras.getInt("money"));
        Bundle bundle = new Bundle();
        bundle.putInt("money", perStudent);
        setResultExtras(bundle);
    }
}

贫困学生广播接收者:

public class PoorStudentReceiver extends BroadcastReceiver {
    private static final String TAG = "PoorStudentReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle resultExtras = getResultExtras(true);
        int money = resultExtras.getInt("money");
        Log.d(TAG, "接收到捐款 --> " + money);
        Log.d(TAG, "感谢各位好心人士...");
    }
}

注册广播的代码,通过android:priority来设置各个接收者的优先级:


    
    
        
    



    
        
    




    
        
    




    
        
    

通过abortBroadcast来终止广播往下传递。

abortBroadcast();

四、静态注册和动态注册

  • 两种注册方式的区别
    静态注册可以一直监听着,即使应用没有起来,也可以监听着,但是耗资源,长期监听着。
    静态注册的广播优先级高于动态注册的广播。
    动态注册的优点就是省资源,需要的时候才监听,不需要的时候需要取消注册。
  • 不可以静态注册的广播,下面这些广播,只可以动态注册。
    android.intent.action.SCREEN_ON
    android.intent.action.SCREEN_OFF
    android.intent.action.BATTERY_CHANGED
    android.intent.action.CONFIGURATION_CHANGED
    android.intent.action.TIME_TICK
    为什么不可以静态注册?
    如果不是必须一直监听着的广播,如果一直监听着会消耗资源,所以静态注册会提高系统的效率。而动态注册的话需要释放资源取消注册,否则会报错的。这样子有利于提高系统的速度。

你可能感兴趣的:(Android开发基础-四大组件之Broadcast)