在喜马拉雅项目最后的历史界面中,自己写的时候遇到过如下问题:
第一个问题
一开始我想的是在详情界面点击节目跳转到播放界面的时候就调用HistoryPresenter的add方法,把当前Trackadd到播放历史的数据库中
过程就是从DetailAcitivity响应了适配器的点击事件后,把tracks和当前的索引传到Player的逻辑层,然后在逻辑层中调用回调集合,再在PlayerActivity中的getTrack方法中执行HistoryPresenter.addHistory(track),把当前播放的节目加入历史数据库中
但是真机跑起来并没有成功把节目加入到数据库,在逻辑层中的for循环打了log,把iPlayerCallback打印了出来,发现并没有PlayerActivity,所以得出结论是,点击跳转的时候,setTrack方法比PlayerActivity中的registerViewCallback先执行,然后把HistoryPresenter.addHistory(track)的操作改到MainActivity中执行,因为MainActivity的回调肯定是最先注册的,也肯定会存在,到这bug解决。
第二个问题
解决了点击节目加入历史数据库之后,又想着实现上下首、滑动viewpager、点击Popupwindow也可以加入数据库,这三种动作唯一相同的地方是,都调用了逻辑层的playByIndex(int indexx),然后我就在这个方法里用for循环调用了回调集合
@Override
public void playByIndex(int indexx) {
if (mPlayManager != null) {
mPlayManager.play(indexx);
}
for (IPlayerCallback iPlayerCallback : mIPlayerCallbacks) {
iPlayerCallback.getTrack(mTrack.get(indexx));
}
}
真机跑起来后上下首、滑动viewpager,都可以实现把节目加入数据库中,但是popupwindow点击后就会闪退,闪退之后马上重启app,导致错误log看不清楚,经常这样,不知道为什么,然后我通过手速,截图,截到了错误log
IllegalStateException: attempt to re-open an already-closed
百度查了查,是数据库多线程导致事务错乱的原因,在我的理解看来,具体细节就是:有A、B两个线程,b线程比a线程稍微慢一点点,然后b在封装数据准备插入的时候,a已经把事务关闭了,然后b再去关闭事务的时候就会报错 然后为什么会add两次,找了找代码,发现playByIndex(int indexx)这个方法就执行了两次,在popupwindow的onclick方法打上log,也只是输出一次,想了半天后发现点击popupwindow后,viewpager也会联动,viewpager联动就会执行onPageSelected(int position),这可麻烦了,要联动就不能加入数据库,要数据库就不能联动,,,but,机智的程序员怎么会向bug低头呢,我们在逻辑层新写一个方法
public void History(int indexx) {
//只有ViewPager才调用,Popupwindow不能调用,因为popupwindow调用的同时,
//会调用viewpager的事件,所以会执行两次,就会出现多线程事务错乱
for (IPlayerCallback iPlayerCallback : mIPlayerCallbacks) {
iPlayerCallback.getTrack(mTrack.get(indexx));
}
}
这个方法只让viewpager调用,popupwindow不调用,这样就实现了viewpager滑动、popupwindow点击都可以添加到数据库中
项目结语:
学了十多天,不到半个月,把整个项目经历下来后,学到了很多,mvp架构,UILoad,数据库,sdk文档的使用等等一大堆,遇到bug也不像以前那么怕了,以前遇到bug第一时间想的就是百度、百度、百度,面向百度编程,但是现在遇到bug我感觉有一点小快乐的感觉,跟着打断点,打log,最后把这个鬼找出来,项目能按照理想状态运行,带给自己正反馈,还有就是别和bug犟,有几次找bug找到11点多,心情很不美好,最后也没找出来,带着沉重的心情躺到床上,第二天起来花了一会儿就把昨天晚上de了半天的bug顺手宰掉了,鲁迅说得好:"当你想找一件东西的时候,就永远找不到,当你不想找的时候,不经意间,它自己就会出现在你面前",下一个项目走起,康师傅万岁!