巨坑,PendingIntent.getBroadcast

说到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     //<span style="box-sizing: border-box; color: rgb(75, 75, 75); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 20px;">如果PendingIntent已经存在,那么当前的PendingIntent会取消掉,然后产生一个新的PendingIntent。</span>
2,PendingIntent.FLAG_NO_CREATE         //<span style="box-sizing: border-box; color: rgb(75, 75, 75); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 20px;">如果PendingIntent不存在,简单了当返回null。</span>
3,PendingIntent.FLAG_ONE_SHOT          //<span style="box-sizing: border-box; color: rgb(75, 75, 75); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 20px;">PendingIntent只能使用一次。调用了实例方法send()之后,它会被自动cancel掉,再次调用send()方法将失败。</span>
4,PendingIntent.FLAG_UPDATE_CURRENT    //<span style="box-sizing: border-box; color: rgb(75, 75, 75); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 20px;">如果PendingIntent已经存在,保留它并且只替换它的extra数据(坑就坑在这里了,这里的条件是如果intent中只有</span><pre name="code" class="java"><span style="box-sizing: border-box; font-family: Verdana, Arial, Helvetica, sans-serif;">extra数据不同,将不会替换</span><span style="box-sizing: border-box; font-family: Verdana, Arial, Helvetica, sans-serif;">extra数据</span><span style="font-family: Verdana, Arial, Helvetica, sans-serif;">);</span>
 

现在,我们换上第四个参数

      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);
	}
运行结果:还是取到第一组是数据。写到这里,答案毫无悬念了。这就是细节决定成败了,好在老大测试的认真,否则到项目上线后在发现问题就难改了。

其实偶尔犯犯二是可以原谅的,最组要的是能够及时改正过来。微笑

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值