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 long clearCache(BaseDanmaku oldValue) {
   if (oldValue.cache.hasReferences()) {
     oldValue.cache.decreaseReference();
     oldValue.cache = null;
     return 0;
   }
   long size = sizeOf(oldValue);
   oldValue.cache.destroy();
   oldValue.cache = null;
   return size;
 }
 private void releaseDanmakuCache(BaseDanmaku item, DrawingCache cache) {
   if (cache == null) {
     cache = (DrawingCache) item.cache;
   }
   item.cache = null;
   if (cache == null) {
     return;
   }
   cache.destroy();
   mCachePool.release(cache);
 }
 @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;
   }
 }
      private byte buildCache(BaseDanmaku item, boolean forceInsert) {

        // measure
        if (!item.isMeasured()) {
          item.measure(mDisp);
        }

        DrawingCache cache = null;
        try {
          // try to find reuseable cache
          BaseDanmaku danmaku = findReuseableCache(item, true, 20);
          if (danmaku != null) {
            cache = (DrawingCache) danmaku.cache;
          }
          if (cache != null) {
            cache.increaseReference();
            item.cache = cache;
            // Log.w("cache", danmaku.text + "DrawingCache hit!!:" + item.paintWidth + "," +
            // danmaku.paintWidth);
            mCacheManager.push(item, 0, forceInsert);
            return RESULT_SUCCESS;
          }

          // try to find reuseable cache from timeout || no-refrerence caches
          danmaku = findReuseableCache(item, false, 50);
          if (danmaku != null) {
            cache = (DrawingCache) danmaku.cache;
          }
          if (cache != null) {
            danmaku.cache = null;
            // Log.e("cache", danmaku.text + "DrawingCache hit!!:" + item.paintWidth + "," +
            // danmaku.paintWidth);
            cache = DanmakuUtils.buildDanmakuDrawingCache(item, mDisp, cache); // redraw
            item.cache = cache;
            mCacheManager.push(item, 0, forceInsert);
            return RESULT_SUCCESS;
          }

          // guess cache size
          if (!forceInsert) {
            int cacheSize =
                DanmakuUtils.getCacheSize((int) item.paintWidth, (int) item.paintHeight);
            if (mRealSize + cacheSize > mMaxSize) {
              //                        Log.d("cache", "break at MaxSize:"+mMaxSize);
              return RESULT_FAILED;
            }
          }

          cache = mCachePool.acquire();
          cache = DanmakuUtils.buildDanmakuDrawingCache(item, mDisp, cache);
          item.cache = cache;
          boolean pushed = mCacheManager.push(item, sizeOf(item), forceInsert);
          if (!pushed) {
            releaseDanmakuCache(item, cache);
            // Log.e("cache", "break at push failed:" + mMaxSize);
          }
          return pushed ? RESULT_SUCCESS : RESULT_FAILED;

        } catch (OutOfMemoryError e) {
          // Log.e("cache", "break at error: oom");
          releaseDanmakuCache(item, cache);
          return RESULT_FAILED;
        } catch (Exception e) {
          // Log.e("cache", "break at exception:" + e.getMessage());
          releaseDanmakuCache(item, cache);
          return RESULT_FAILED;
        }
      }
 @Override
 public void handleMessage(Message msg) {
   int what = msg.what;
   switch (what) {
     case PREPARE:
       evictAllNotInScreen();
       for (int i = 0; i < 300; i++) {
         mCachePool.release(new DrawingCache());
       }
     case DISPATCH_ACTIONS:
       // Log.e(TAG,"dispatch_actions:"+mCacheTimer.currMillisecond+":"+mTimer.currMillisecond);
       long delayed = dispatchAction();
       if (delayed <= 0) {
         delayed = mContext.mDanmakuFactory.MAX_DANMAKU_DURATION / 2;
       }
       sendEmptyMessageDelayed(DISPATCH_ACTIONS, delayed);
       break;
     case BUILD_CACHES:
       removeMessages(BUILD_CACHES);
       boolean repositioned = ((mTaskListener != null && mReadyState == false) || mSeekedFlag);
       prepareCaches(repositioned);
       if (repositioned) mSeekedFlag = false;
       if (mTaskListener != null && mReadyState == false) {
         mTaskListener.ready();
         mReadyState = true;
       }
       //
       // Log.i(TAG,"BUILD_CACHES:"+mCacheTimer.currMillisecond+":"+mTimer.currMillisecond);
       break;
     case ADD_DANMAKKU:
       BaseDanmaku item = (BaseDanmaku) msg.obj;
       addDanmakuAndBuildCache(item);
       break;
     case REBUILD_CACHE:
       Pair<BaseDanmaku, Boolean> pair = (Pair<BaseDanmaku, Boolean>) msg.obj;
       if (pair != null) {
         BaseDanmaku cacheitem = pair.first;
         if (pair.second) {
           cacheitem.requestFlags |= BaseDanmaku.FLAG_REQUEST_REMEASURE;
         }
         cacheitem.requestFlags |= BaseDanmaku.FLAG_REQUEST_INVALIDATE;
         if (!pair.second && cacheitem.hasDrawingCache() && !cacheitem.cache.hasReferences()) {
           DrawingCache cache =
               DanmakuUtils.buildDanmakuDrawingCache(
                   cacheitem, mDisp, (DrawingCache) cacheitem.cache);
           cacheitem.cache = cache;
           push(cacheitem, 0, true);
           return;
         }
         if (cacheitem.isLive) {
           clearCache(cacheitem);
           createCache(cacheitem);
         } else {
           entryRemoved(true, cacheitem, null);
           addDanmakuAndBuildCache(cacheitem);
         }
       }
       break;
     case CLEAR_TIMEOUT_CACHES:
       clearTimeOutCaches();
       break;
     case SEEK:
       Long seekMills = (Long) msg.obj;
       if (seekMills != null) {
         mCacheTimer.update(seekMills.longValue());
         mSeekedFlag = true;
         evictAllNotInScreen();
         resume();
       }
       break;
     case QUIT:
       removeCallbacksAndMessages(null);
       mPause = true;
       evictAll();
       clearCachePool();
       this.getLooper().quit();
       break;
     case CLEAR_ALL_CACHES:
       evictAll();
       mCacheTimer.update(
           mTimer.currMillisecond - mContext.mDanmakuFactory.MAX_DANMAKU_DURATION);
       mSeekedFlag = true;
       break;
     case CLEAR_OUTSIDE_CACHES:
       evictAllNotInScreen(true);
       mCacheTimer.update(mTimer.currMillisecond);
       break;
     case CLEAR_OUTSIDE_CACHES_AND_RESET:
       evictAllNotInScreen(true);
       mCacheTimer.update(mTimer.currMillisecond);
       requestClear();
       break;
   }
 }