diff --git a/DanmakuFlameMaster/src/main/java/master/flame/danmaku/controller/CacheManagingDrawTask.java b/DanmakuFlameMaster/src/main/java/master/flame/danmaku/controller/CacheManagingDrawTask.java index 154ac72e..886acb0c 100644 --- a/DanmakuFlameMaster/src/main/java/master/flame/danmaku/controller/CacheManagingDrawTask.java +++ b/DanmakuFlameMaster/src/main/java/master/flame/danmaku/controller/CacheManagingDrawTask.java @@ -77,6 +77,19 @@ public void addDanmaku(BaseDanmaku danmaku) { mCacheManager.addDanmaku(danmaku); } + @Override + protected void onDanmakuRemoved(BaseDanmaku danmaku) { + super.onDanmakuRemoved(danmaku); + if (danmaku.hasDrawingCache()) { + if (danmaku.cache.hasReferences()) { + danmaku.cache.decreaseReference(); + } else { + danmaku.cache.destroy(); + } + danmaku.cache = null; + } + } + @Override public RenderingState draw(AbsDisplayer displayer) { RenderingState result = super.draw(displayer); @@ -178,7 +191,14 @@ public void seek(long mills) { public void addDanmaku(BaseDanmaku danmaku) { if (mHandler != null) { - mHandler.obtainMessage(CacheHandler.ADD_DANMAKKU, danmaku).sendToTarget(); + if (danmaku.isLive) { + if (danmaku.isTimeOut()) { + return; + } + mHandler.createCache(danmaku); + } else { + mHandler.obtainMessage(CacheHandler.ADD_DANMAKKU, danmaku).sendToTarget(); + } } } @@ -450,19 +470,7 @@ public void handleMessage(Message msg) { break; case ADD_DANMAKKU: BaseDanmaku item = (BaseDanmaku) msg.obj; - if (item.isTimeOut()) { - break; - } - if (item.priority == 0 && item.isFiltered()) { - break; - } - if (!item.hasDrawingCache()) { - buildCache(item); - } - if (item.isLive) { - mCacheTimer.update(mTimer.currMillisecond - + DanmakuFactory.MAX_DANMAKU_DURATION * mScreenSize); - } + addDanmakuAndBuildCache(item); break; case CLEAR_TIMEOUT_CACHES: clearTimeOutCaches(); @@ -560,12 +568,16 @@ private long prepareCaches(boolean repositioned) { synchronized (danmakuList) { danmakus = danmakuList.subnew(curr, end); } - if (danmakus == null || danmakus.isEmpty()) { + if (danmakus == null) { mCacheTimer.update(end); return 0; } BaseDanmaku first = danmakus.first(); BaseDanmaku last = danmakus.last(); + if (first == null || last == null) { + mCacheTimer.update(end); + return 0; + } long deltaTime = first.time - mTimer.currMillisecond; long sleepTime = 30 + 10 * deltaTime / DanmakuFactory.MAX_DANMAKU_DURATION; sleepTime = Math.min(100, sleepTime); @@ -657,6 +669,34 @@ private long prepareCaches(boolean repositioned) { return consumingTime; } + public boolean createCache(BaseDanmaku item) { + // measure + if (!item.isMeasured()) { + item.measure(mDisp); + } + DrawingCache cache = null; + try { + cache = mCachePool.acquire(); + cache = DanmakuUtils.buildDanmakuDrawingCache(item, mDisp, cache); + item.cache = cache; + } catch (OutOfMemoryError e) { +//Log.e("cache", "break at error: oom"); + if (cache != null) { + mCachePool.release(cache); + } + item.cache = null; + return false; + } catch (Exception e) { +//Log.e("cache", "break at exception:" + e.getMessage()); + if (cache != null) { + mCachePool.release(cache); + } + item.cache = null; + return false; + } + return true; + } + private byte buildCache(BaseDanmaku item) { // measure @@ -721,6 +761,25 @@ private byte buildCache(BaseDanmaku item) { } } + private final void addDanmakuAndBuildCache(BaseDanmaku danmaku) { + if (danmaku.isTimeOut()) { + return; + } + if (danmaku.priority == 0 && danmaku.isFiltered()) { + return; + } + if (!danmaku.isLive && danmaku.isLate() && danmaku.time > mCacheTimer.currMillisecond + DanmakuFactory.MAX_DANMAKU_DURATION) { + return; + } + if (!danmaku.hasDrawingCache()) { + buildCache(danmaku); + } + if (danmaku.isLive) { + mCacheTimer.update(mTimer.currMillisecond + + DanmakuFactory.MAX_DANMAKU_DURATION * mScreenSize); + } + } + public void begin() { sendEmptyMessage(PREPARE); sendEmptyMessageDelayed(CLEAR_TIMEOUT_CACHES, DanmakuFactory.MAX_DANMAKU_DURATION); diff --git a/DanmakuFlameMaster/src/main/java/master/flame/danmaku/controller/DrawTask.java b/DanmakuFlameMaster/src/main/java/master/flame/danmaku/controller/DrawTask.java index dee8deb4..8ff9be40 100644 --- a/DanmakuFlameMaster/src/main/java/master/flame/danmaku/controller/DrawTask.java +++ b/DanmakuFlameMaster/src/main/java/master/flame/danmaku/controller/DrawTask.java @@ -123,6 +123,10 @@ public synchronized void removeAllDanmakus() { danmakuList.clear(); } + protected void onDanmakuRemoved(BaseDanmaku danmaku) { + // TODO call callback here + } + @Override public synchronized void removeAllLiveDanmakus() { if (danmakus == null || danmakus.isEmpty()) @@ -130,8 +134,10 @@ public synchronized void removeAllLiveDanmakus() { synchronized (danmakus) { IDanmakuIterator it = danmakus.iterator(); while (it.hasNext()) { - if (it.next().isLive) { + BaseDanmaku danmaku = it.next(); + if (danmaku.isLive) { it.remove(); + onDanmakuRemoved(danmaku); } } } @@ -142,13 +148,12 @@ protected synchronized void removeUnusedLiveDanmakusIn(int msec) { return; long startTime = System.currentTimeMillis(); IDanmakuIterator it = danmakuList.iterator(); - int count = 0; while (it.hasNext()) { BaseDanmaku danmaku = it.next(); boolean isTimeout = danmaku.isTimeOut(); if (isTimeout && danmaku.isLive) { it.remove(); - count++; + onDanmakuRemoved(danmaku); } if (!isTimeout || System.currentTimeMillis() - startTime > msec) { break; diff --git a/DanmakuFlameMaster/src/main/java/master/flame/danmaku/danmaku/model/android/Danmakus.java b/DanmakuFlameMaster/src/main/java/master/flame/danmaku/danmaku/model/android/Danmakus.java index dd3fa4f4..ac364ad9 100644 --- a/DanmakuFlameMaster/src/main/java/master/flame/danmaku/danmaku/model/android/Danmakus.java +++ b/DanmakuFlameMaster/src/main/java/master/flame/danmaku/danmaku/model/android/Danmakus.java @@ -178,7 +178,7 @@ private Collection subset(long startTime, long endTime) { @Override public IDanmakus subnew(long startTime, long endTime) { Collection subset = subset(startTime, endTime); - if (subset == null) { + if (subset == null || subset.isEmpty()) { return null; } ArrayList newSet = new ArrayList(subset);