您的位置:首页 > 移动开发 > Android开发

【oschina android源码分析】页面通知(站内信)的设计-android轮询方案

2016-05-21 18:29 543 查看
  站内信采用的是一个android系统下常见的轮询方案。包括:

NoticeService是轮询所在的服务,自己单独一个进程。定时消息,网络请求都封装在改服务中。

NoticeUtils扮演客户端,去绑定NoticeService。

INoticeService.aidl是进程间通信的aidl文件。

AlarmReceiver。

  该aidl文件的设计:

interface INoticeService
{
void scheduleNotice();
void requestNotice();//请求网络
void clearNotice(int uid,int type);//停止请求
}


  因为客户端需要调用requestNotice和clearNotice方法,所以需要在INoticeService中增加这两个方法,但是scheduleNotice客户端并不需要调用,所以这里是可以删除的,我们只需要在aidl文件中声明客户端需要调用的方法即可,不需要的可以删除。

aidl文件的设计也是非常关键的。

一.具体流程

1.使用系统服务AlarmManager来定时开启一个广播接收者。NoticeService中

// 从1秒后开始,每隔2分钟执行getOperationIntent()
mAlarmMgr.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + 1000, INTERVAL,
getOperationIntent());


说明:

AlarmManager是一个android系统服务,不会受锁屏等等的影响,是比较靠谱的轮询解决方案。

2.定时启动一个广播接收者。NoticeService

OSC采用轮询方式实现消息推送,每次被调用都去执行一次{@link #AlarmReceiver}onReceive()方法
private PendingIntent getOperationIntent() {
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent operation = PendingIntent.getBroadcast(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
return operation;
}


说明:

因为AlarmManager必须接收一个pendingintent作为参数,所以除了广播接收者,服务之外确实没有更好的选择了,所以这里也是可以选择使用服务的,使用startService的方式,在onStartCommand方法中来实进行网络请求。

3.广播接收者。

public class AlarmReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
TLog.log("onReceive ->net.oschina.app收到定时获取消息");

NoticeUtils.requestNotice(context);
}
}


说明:

即使该广播接受者是由noticeservice所在的服务启动的,该广播接受者仍属于app的进程,所以onreceive方法仍要在app所在的进程执行,仍属于跨进程的。要跨进程去调用noticeservice中的方法,这里选择还是NoticeUtils。省去了再写一个客户端的烦恼。

4.广播接受者调用的网络请求。NoticeUtils中

public static void requestNotice(Context context) {
if (sService != null) {
try {
TLog.log("requestNotice...");
sService.requestNotice();
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
context.sendBroadcast(new Intent(
NoticeService.INTENT_ACTION_REQUEST));
TLog.log("requestNotice,service is null");
}
}


5.接收到网络请求后,会发送广播。

/**
* 发送通知广播
*
* @param context
* @param notice
*/
public static void sendBroadCast(Context context, Notice notice) {
if (!((AppContext) context.getApplicationContext()).isLogin()
|| notice == null)
return;
Intent intent = new Intent(Constants.INTENT_ACTION_NOTICE);
Bundle bundle = new Bundle();
bundle.putSerializable("notice_bean", notice);
intent.putExtras(bundle);
context.sendBroadcast(intent);
}


说明:

需要接受消息的页面要注册广播接受者,来接受该广播。(广播可以跨进程)

二.一些问题

三.资料参考

http://www.kymjs.com/code/2015/01/13/01
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: