Android源码Transition.java中发现一个小bug

修复Scene Transition中ID指定view动画切换的bug
本文详细描述了在Scene Transition部分遇到的一个bug,即通过ID指定view进行动画切换时出现的ArrayList越界错误。作者通过分析源码,发现了在remove方法中存在的逻辑错误,并在Android源码官网提交了问题报告。最后,文章表达了作者对于能够为开源社区做出贡献的小欣慰。
最近两天正在看Scene+Transition部分,感觉这部分挺有空间可挖。该部分的功能是,在同一组ViewGroup结构的两个不同状态之间做动画切换,这有助于用户知道某一个状态的由来。更进一步,在这组ViewGroup结构中,可以选择部分view做动画切换,部分则不。这是个有趣的功能,所以写了小段代码测试。

选择view可以多个方法,比如直接指定view,通过view的id,名字,或种类。不幸的是,通过指定id来指定view的话,其中的remove方法始终出错,报告ArrayList越界。多次尝试后查阅该方法的源码,发现一个小bug。源码:

    public Transition removeTarget(int targetId) {
        if (targetId > 0) {
            mTargetIds.remove(targetId);
        }
        return this;
    }

其对应的add操作如下:

    public Transition addTarget(int targetId) {
        if (targetId > 0) {
            mTargetIds.add(targetId);
        }
        return this;
    }

在add方法中,int类型的targetId被自动转换为Integer类型,当成一个element加进了list。但是在remove方法中,参数是int类型时则对应ArrayList的remove(int position)方法,也即这个targetId被当成ArrayList的偏移量了,也即remove操作的是偏移量为targetI的的元素,而不是数值为targetId的那个元素,这显然不对。考虑到我们一般使用R.id.view_id这个参数来add和remove,故这个remove方法几乎必然越界。

查询Stackoverflow并google之后没有发现相关信息,于是在Android源码官网上提交了这个小bug:https://code.google.com/p/android/issues/detail?id=163184。由于这个bug简单清晰且对应到源码的具体方法了,所以半小时后即获得确认,状态由New变成Assigned。

小欣慰一下,这也算自己为开源事业做了绵薄的贡献吧。

Fatal Exception: java.lang.IllegalStateException: Can't sync on 2 engines simultaneously currentSyncId=215 newSyncId=221 at android.os.Parcel.createExceptionOrNull(Parcel.java:3019) at android.os.Parcel.createException(Parcel.java:2995) at android.os.Parcel.readException(Parcel.java:2978) at android.os.Parcel.readException(Parcel.java:2920) at android.app.IActivityClientController$Stub$Proxy.activityPaused(IActivityClientController.java:1226) at android.app.ActivityClient.activityPaused(ActivityClient.java:75) at android.app.servertransaction.PauseActivityItem.postExecute(PauseActivityItem.java:64) at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:177) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2304) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7950) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936) Caused by android.os.RemoteException: Remote stack trace: at com.android.server.wm.WindowContainer.setSyncGroup(WindowContainer.java:3650) at com.android.server.wm.BLASTSyncEngine$SyncGroup.addToSync(BLASTSyncEngine.java:240) at com.android.server.wm.BLASTSyncEngine$SyncGroup.-$$Nest$maddToSync(Unknown Source:0) at com.android.server.wm.BLASTSyncEngine.addToSyncSet(BLASTSyncEngine.java:329) at com.android.server.wm.Transition.collect(Transition.java:428)
最新发布
08-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值