说到PendingIntent,很自然的反应AppWidget,RemoteView,Notification。这些关联似乎把他们串在了一起。最近一个项目要用到widget日历。由于RemoteViews支持的空间不多(其中就不支持CalendarView),没办法,只能在布局中用TextView填充成一个日历了。其中就有一个问题急需解决,就是需求要就点击日历跳转到相应的日期界面,这下可出问题了。大家可能会疑问其实不就是pendingIntent.getActvity()嘛,没什么大不了。首先,日历一共35个TextView,每个如果都装载一个pendingIntent的话,事情就闹大了,widget的更新卡的要命。这样的用户体验肯定是不行的,如何解决就摆在了面前。
说到这里,我们不得不提Widget更新的一个特性。Widget的更新主要就在RemoteViews身上。RemoteViews并不是一个真正的View,它只是View的一个描述而已,所以,当RemoteViews中的属性跟原来的一样时,widget并不会去更新该部分。说到这那就好办了,在更新widget时,唯一不变的是TextView自身对应的坐标,所以只要pengdingIntent中的所有数据都一样时,就不再会影响性能了。
public void updateEvent(RemoteViews remote,int i,int j){
Intent intent = new Intent("action");
intent.putExtra("x", i);
intent.putExtra("y", j);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
remote.setOnClickPendingIntent(getId(i,j), pendingIntent);
}
自信总会使人盲目,我就这样提交了上去。一个功能完成。
但很快,一个bug记录返了回来:日历点击没有跳转到相应的日期。这算是一个晴天霹雳,怎么可能,思维扫描一遍,没有逻辑错误。只有调试才能知道真相。
很快就发现,绑定的数据跟接收到的数据不一样。不断点击那个,数据永远是第一条记录的数据。我的脑袋瞬间短路。虽然百思不得其解,当老大的催促使得我顾不得更多探查。此路不通,那就绕路过呗。让后我改为
public void updateEvent(RemoteViews remote,int i,int j){
Intent intent = new Intent(this,OpenCalendarActivity.class);
intent.setAction(i+","+j);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
remote.setOnClickPendingIntent(getId(i,j), pendingIntent);
}
想想可能数据传输问题,但结果是一样的,只能取到第一组数据。无奈之下,只能去看API文档了。后来才发现,原来
PendingIntent.getBroadcast();其中有文章;这涉及到他的第四个参数
1,PendingIntent.FLAG_CANCEL_CURRENT //如果PendingIntent已经存在,那么当前的PendingIntent会取消掉,然后产生一个新的PendingIntent。
2,PendingIntent.FLAG_NO_CREATE //如果PendingIntent不存在,简单了当返回null。
3,PendingIntent.FLAG_ONE_SHOT //PendingIntent只能使用一次。调用了实例方法send()之后,它会被自动cancel掉,再次调用send()方法将失败。
4,PendingIntent.FLAG_UPDATE_CURRENT //如果PendingIntent已经存在,保留它并且只替换它的extra数据(坑就坑在这里了,这里的条件是如果intent中只有extra数据不同,将不会替换extra数据);
现在,我们换上第四个参数
public void updateEvent(RemoteViews remote,int i,int j){
Intent intent = new Intent(this,OpenCalendarActivity.class);
intent.putExtra("x", i);
intent.putExtra("y", j);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
remote.setOnClickPendingIntent(getId(i,j), pendingIntent);
}
运行结果:还是取到第一组是数据。写到这里,答案毫无悬念了。这就是细节决定成败了,好在老大测试的认真,否则到项目上线后在发现问题就难改了。
其实偶尔犯犯二是可以原谅的,最组要的是能够及时改正过来。