这是我参与「第四届青训营 」笔记创作活动的第4天。
4 Broadcast
4.1 Broadcast是什么
Android中的广播主要可以分为两种类型:标准广播和无序广播
- 标准广播(normal broadcasts)是一种完全异步执行的广播,在广播发出之后,所有的BroadcastReceiver几乎会在同一时刻收到这条广播消息,因此它们之间没有任何先后顺序可言。这种广播的效率会比较高,同时也意味着它是无法被截断的。
- 有序广播(order broadcasts)是一种同步执行的广播,同一时刻只会有一个BroadcastReceiver能够收到这条广播消息,当这个BroadcastReceiver中的逻辑执行完毕后,广播才会继续传播。所以此时的BroadcastReceiver是有先后顺序的,优先级高的BroadcastReceiver就可以先收到广播消息,并且前面的BroadcastReceiver还可以截断正在传递的广播,这样后面的BroadcastReceiver就无法收到广播消息了。
4.2 Broadcast基本用法
4.2.1 静态注册BroadcastReceiver
在AndroidMainfest.xml中注册:
<receiver
android:name=".AnotherBroadcastReceiver"
android:enabled="true"
android:exported="true">
<!--设置广播接收器的优先级,取整数值,数值大的优先级高-->
<intent-filter android:priority="100">
<action android:name="cn.edu.jssvc.wangyu.mybroadcasttest.MY_BROADCAST" />
</intent-filter>
</receiver>
BroadcastReceiver实现类:
public class AnotherBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"我是另外一个广播接收器",Toast.LENGTH_LONG).show();
}
}
4.2.2 动态注册BroadcastReceiver
BroadcastReceiver实现类:
private class ForceOfflineReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, Intent intent) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("提示");
builder.setMessage("你已经被强制下线 请尝试再次登录");
builder.setCancelable(false);
builder.setPositiveButton("好的", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
ActivityCollector.finishAll();//销毁所有活动
Intent intent = new Intent(context,LoginActivity.class);
context.startActivity(intent);//重新启动LoginActivity
}
});
builder.show();
}
}
动态注册BroadcastReceiver的主要代码:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("cn.edu.jssvc.wangyu.wybroadcastbestpractice.FORCE_OFFLINE");
receiver = new ForceOfflineReceiver();
registerReceiver(receiver,intentFilter);
动态注册的广播接收器是需要取消注册的,只需要调用unregisterReceiver()即可
4.2.3 发送广播
-
发送标准(无序)广播:
Intent intent = new Intent("cn.edu.jssvc.wangyu.mybroadcasttest.MY_BROADCAST"); //出于安全考虑,目前自定义广播意图必须设置应用所在包名 intent.setPackage(getPackageName()); sendBroadcast(intent); -
发送无序广播:
Intent intent = new Intent("cn.edu.jssvc.wangyu.mybroadcasttest.MY_BROADCAST"); //出于安全考虑,目前自定义广播意图必须设置应用所在包名 intent.setPackage(getPackageName()); sendOrderedBroadcast(intent,null);
4.3 常用系统广播
- Intent.ACTION_CONNECTIVITY_CHANGE
- Intent.ACTION_BATTERY_CHANGED
- Intent.ACTION_SCREEN_ON
- Intent.ACTION_SCREEN_OFF
- Intent.ACTION_PACKAGE_INSTALL
- Intent.ACTION_BOOT_COMLETED
- Intent.ACTION_PACKAGE_ADDED
- Intent.ACTION_PACKAGE_REPLACED
- Intent.ACTION_PACKAGE_REMOVED
5 ContentProvider
5.1 ContentProvider是什么
ContentProvider主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访问数据的安全性。目前,使用ContentProvider是Android实现跨程序共享数据的标准方式。
5.2 创建一个ContentProvider
-
在AndroidStudio中,右击包名→New→Other→Content,最后会弹出一个如下窗口:
ps:Exported属性表示是否允许外部程序访问这个ContentProvider,Enabled属性表示是否启动这个ContentProvider
-
在AndroidMainfest.xml中对ContentPrvider声明(使用步骤1方法创建会自动声明):
<provider android:name=".DatabaseProvider" android:authorities="com.example.databasetest.provider" android:enabled="true" android:exported="true"></provider> -
对创建的ContentProvider实现类中的方法进行重写
-
onCreate()
初始化ContentProvider的时候调用。通常会在这里完成对数据库的创建和升级等操作,返回true表示ContentProvider初始化成功,返回false则表示失败。
-
query()
从ContentProvider中查询数据。uri参数用于确定查询哪张表,projection参数用于确定查询哪些列,selection和selectionArgs参数用于约束查询哪些行,sortOrder参数用于对结果进行排序,查询的结果存放在Cursor对象中返回。
-
insert()
向ContentProvider中添加一条数据。uri参数用于确定要添加到的表,待添加的数据保存在values参数中。添加完成后,返回一个用于表示这条新记录的URI。
-
update()
更新ContentProvider中已有的数据。uri参数用于确定更新哪一张表中的数据,新数据保存在values参数中,selection和selectionArgs参数用于约更新哪些行,受影响的行数将作为返回值返回。
-
delete()
从ContentProvider中删除数据。uri参数用于确定删除哪一张表中的数据,selection和selectionArgs参数用于约束删除哪些行,被删除的行数将作为返回值返回。
-
getType()
根据传入的内容URI返回相应的MIME类型。
-
5.3 使用ContentResolver访问ContentProvider中共享的数据
这是对一个的ContentProvider中update()方法的使用示例:
// 更新数据
Uri uri = Uri.parse("content://com.example.databasetest.provider/book/" + newId);
ContentValues values = new ContentValues();
values.put("name", "A Storm of Swords");
values.put("pages", 1216);
values.put("price", 24.05);
getContentResolver().update(uri, values, null, null);
6 Handler
6.1 Handler是什么
Handler顾名思义就是处理者的意思,它主要用于发送和处理消息的。发送消息一般是使用Handler的sendMessage()方法、post()方法等,而发出的消息经过一系列地辗转处理后最终会传递到Handler地handleMessage()方法中。
6.2 相关的几个概念
-
Message
Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间传递数据。
-
MessageQueue
MessageQueue是消息队列的意思,它主要用于存在所有通过Handler发送的消息。这部分消息会一直存在于消息队列中,等待被处理。每个线程中只会有一个MessageQueue对象。
-
Looper
Looper是每个线程中的MessageQueue的管家,调用Looper的loop()方法后,就会进入一个无限循环当中,然后每当发现MessageQueue中存在一条消息时,就会将它取出,并传递到Handler的handleMessage()方法中。每个线程中只会有一个Looper对象。
6.3 Handler基本用法
-
创建:新建Handler,实现handleMessage(Message)
// 在UI主线程中创建可以跨线程传递数据的Handler对象,需要将一个MainLooper传递给构造方法 private Handler handler = new Handler(Looper.getMainLooper()) { //实现handleMessage(),接收另一个线程发送来的Message对象 public void handleMessage(Message msg) { // 根据Message的what字段判断消息对象是誰 switch (msg.what) { case UPDATE_TEXT: // 从Message对象中取得obj字段携带的数据,这个字段是Object类型,可以携带任意类型+ String str = (String) msg.obj; // 通过主界面中的TextView显示传递回来的数据 textView.setText(str); break; default: break; } } }; -
构造Message:what/setData()
-
发送:子线程调用Handler.sendMessage(Message)发送Message
new Thread(new Runnable() { @Override // 实现线程方法run(),这个方法中代码将运行在新开辟的线程中 public void run() { // 创建Message对象 Message message = new Message(); // 设置Message对象的what字段值 message.what = UPDATE_TEXT; // 设置Message对象的obj字段值,obj可以保存各种类型的数据 message.obj = "大家好!我是后台线程产生的字符串!"; // 调用Handler类对象的sendMessage()方法将数据传递回主线程 handler.sendMessage(message);//将Message对象发送出去 } }).start();// 调用Thread实例的start()启动线程运行 -
处理:在Handler的handleMessage(Message msg)主线程更新UI
7 Binder
7.1 Binder是什么
Binder是一种进程间的通信机制,基于开源的OpenBinder实现;OpenBinder起初由Be Inc.开发,后由Plam Inc.接手。从字面上来解释Binder有胶水、粘合剂的意思,顾名思义就是粘合不同的进程,使之实现通信。
7.2 常用IPC方案对比
7.3 Binder基本用法
服务端
- 定义一个AIDL文件
- 实现描述的接口,编写service
- 如果有实体类,需要提供实体类(jar包形式)
客户端
- 拿到AIDL文件
- 绑定服务,获得接口持有对象
7.4 Binder核心原理
三、总结
在之前Androi开发的学习中,学习的知识比较零散,东边一锄头西边一榔头的,经过这次对于Android基础知识的学习,使我对于Android知识体系有了更深的理解,后面还有很多的知识需要去学习,加油!