CacheManagingDrawTask.java
0.5.0 public void invalidateDanmaku(BaseDanmakudanmaku, boolean remeasure) {
if(mHandler != null) {
mHandler.requestCancelCaching();
Pair<BaseDanmaku, Boolean> pair = newPair<>(danmaku, remeasure);
mHandler.obtainMessage(CacheHandler.REBUILD_CACHE,pair).sendToTarget();
}
}
0.7.3 public voidinvalidateDanmaku(BaseDanmaku danmaku, boolean remeasure) {
if(mHandler != null) {
mHandler.requestCancelCaching();
mHandler.obtainMessage(CacheHandler.REBUILD_CACHE, danmaku).sendToTarget();
}
}
0.5.0的参数存储的是BaseDanmaku和Boolean类型的remaeasure值,
0.7.3的参数只保留了BaseDanmaku。
对应的CacheHandler中的handlerMessage处理方法:
0.5.0 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.measureResetFlag++;
}
cacheitem.requestFlags |=BaseDanmaku.FLAG_REQUEST_INVALIDATE;
IDrawingCache<?> cache =cacheitem.getDrawingCache();
if (!pair.second &&cache != null && cache.get() !=null && !cache.hasReferences()){
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;
0.7.3 case REBUILD_CACHE:
BaseDanmaku cacheitem =(BaseDanmaku) msg.obj;
if (cacheitem != null) {
IDrawingCache<?> cache = cacheitem.getDrawingCache();
boolean requestRemeasure = 0 != (cacheitem.requestFlags &BaseDanmaku.FLAG_REQUEST_REMEASURE);
if (!requestRemeasure &&cache != null && cache.get() !=null && !cache.hasReferences()){
cache =DanmakuUtils.buildDanmakuDrawingCache(cacheitem, mDisp, (DrawingCache)cacheitem.cache);
cacheitem.cache = cache;
push(cacheitem, 0, true);
return;
}
if(cacheitem.isLive) {
clearCache(cacheitem);
createCache(cacheitem);
} else {
if (cache != null &&cache.hasReferences()) {
cache.destroy();
}
entryRemoved(true,cacheitem, null);
addDanmakuAndBuildCache(cacheitem);
}
}
break;
新增代码:
if(cache != null && cache.hasReferences()) {
cache.destroy();
}
0.5.0中从Pair中取出了BaseDanmaku和Boolean remeasure,如果remeasure为ture则更新Baseitem的measureResetFlag值。
0.7.3中直接通过BaseDanmaku的requestFlags和FLAG_REQUEST_REMEASURE给自定义变量赋值,然后执行相应操作。
优点:代码更简洁。
0.5.0 private void evictAll() {
if(mCaches != null) {
IDanmakuIterator it = mCaches.iterator();
while (it.hasNext()) {
BaseDanmaku danmaku = it.next();
entryRemoved(true, danmaku, null);
}
mCaches.clear();
}
mRealSize = 0;
}
0.7.0 private void evictAll() {
if (mCaches != null) {
mCaches.forEach(new IDanmakus.DefaultConsumer<BaseDanmaku>() {
@Override
public int accept(BaseDanmaku danmaku) {
entryRemoved(true, danmaku, null);
return ACTION_CONTINUE;
}
});
mCaches.clear();
}
mRealSize = 0;
}
在evictAll函数中,0.5.0通过自定义的IDanmakuIterator遍历mCaches,然后执行 entryRemoved(true, danmaku, null);方法,0.7.3通过mCaches.forEach方法遍历mCaChe,并执行entryRemoved函数,其中forEach方法为Danmakus类添加的方法,用来遍历集合,其中的遍历方法封装了0.5.0中的IDanmakuIterator遍历方法。
0.5.0 private void evictAllNotInScreen(booleanremoveAllReferences)
if(mCaches != null) {
IDanmakuIterator it =mCaches.iterator();
while (it.hasNext()) {
BaseDanmaku danmaku = it.next();
IDrawingCache<?> cache =danmaku.cache;
boolean hasReferences = cache != null&& cache.hasReferences();
if (removeAllReferences &&hasReferences) {
if (cache.get() != null) {
mRealSize -= cache.size();
cache.destroy();
}
entryRemoved(true, danmaku, null);
it.remove();
continue;
}
if(danmaku.isOutside()) {
entryRemoved(true, danmaku, null);
it.remove();
}
}
// mCaches.clear();
}
mRealSize= 0;
0.7.3 private void evictAllNotInScreen(final booleanremoveAllReferences)
if (mCaches != null) {
mCaches.forEach(newIDanmakus.DefaultConsumer<BaseDanmaku>() {
@Override
public int accept(BaseDanmakudanmaku) {
IDrawingCache<?> cache = danmaku.cache;
boolean hasReferences = cache != null&& cache.hasReferences();
if (removeAllReferences &&hasReferences) {
if (cache.get() != null) {
mRealSize -= cache.size();
cache.destroy();
}
entryRemoved(true, danmaku, null);
return ACTION_REMOVE;
}
if(danmaku.isOutside()) {
entryRemoved(true, danmaku, null);
return ACTION_REMOVE;
}
return ACTION_CONTINUE;
}
});
}
0.5.0通过自定义的IDanmakuIterator遍历mCaches
0.7.0通过Danmakus自定义的forEach()方法遍历mCaches
0.5.0 private boolean push(BaseDanmaku item, intitemSize, boolean forcePush) {
while (mRealSize + size >mMaxSize && mCaches.size() > 0) {
BaseDanmaku oldValue = mCaches.first();
if (oldValue.isTimeOut()) {
entryRemoved(false, oldValue, item);
mCaches.removeItem(oldValue);
}
0.7.3 private boolean push(BaseDanmaku item, intitemSize, boolean forcePush) {
while (mRealSize + size > mMaxSize && oldValue != null) {
if (oldValue.isTimeOut()) {
entryRemoved(false, oldValue, item);
mCaches.removeItem(oldValue);
oldValue = mCaches.first();
}
0.5.0中while判断mCaches.size()
0.7.3中while判断oldValue,如果oldValue超时,则调用mCaches.removeItem(),并重新给oldValue赋值。
0.5.0 private void clearTimeOutCaches() {
clearTimeOutCaches(mTimer.currMillisecond);
}
private void clearTimeOutCaches(longtime) {
IDanmakuIterator it =mCaches.iterator();
while (it.hasNext() &&!mEndFlag) {
BaseDanmaku val = it.next();
if (val.isTimeOut()) {
synchronized(mDrawingNotify) {
try {
mDrawingNotify.wait(30);
} catch(InterruptedException e) {
e.printStackTrace();
break;
}
}
entryRemoved(false, val,null);
it.remove();
} else {
break;
}
}
}
0.7.3 private void clearTimeOutCaches() {
mCaches.forEach(newIDanmakus.DefaultConsumer<BaseDanmaku>() {
@Override
public int accept(BaseDanmakuval) {
if (val.isTimeOut()) {
synchronized(mDrawingNotify) {
try {
mDrawingNotify.wait(30);
} catch(InterruptedException e) {
e.printStackTrace();
returnACTION_BREAK;
}
}
entryRemoved(false,val, null);
return ACTION_REMOVE;
} else {
return ACTION_BREAK;
}
}
});
}
0.5.0中通过自定义的IDanmakuIterator遍历
0.7.3中通过forEach遍历。
0.5.0 private BaseDanmakufindReuseableCache(BaseDanmaku refDanmaku,
boolean strictMode,
int maximumTimes) {
IDanmakuIterator it = mCaches.iterator();
int slopPixel = 0;
if (!strictMode) {
slopPixel =mDisp.getSlopPixel() * 2;
}
int count = 0;
while (it.hasNext() && count++ < maximumTimes){ // limit maximum times
BaseDanmaku danmaku = it.next();
IDrawingCache<?> cache =danmaku.getDrawingCache();
if (cache == null ||cache.get() == null) {
continue;
}
if (danmaku.paintWidth ==refDanmaku.paintWidth
&&danmaku.paintHeight == refDanmaku.paintHeight
&&danmaku.underlineColor == refDanmaku.underlineColor
&&danmaku.borderColor == refDanmaku.borderColor
&&danmaku.textColor == refDanmaku.textColor
&&danmaku.text.equals(refDanmaku.text)) {
return danmaku;
}
if (strictMode) {
continue;
}
if (!danmaku.isTimeOut()) {
break;
}
if (cache.hasReferences()) {
continue;
}
float widthGap = cache.width()- refDanmaku.paintWidth;
float heightGap =cache.height() - refDanmaku.paintHeight;
if (widthGap >= 0 &&widthGap <= slopPixel &&
heightGap >= 0&& heightGap <= slopPixel) {
return danmaku;
}
}
return null;
}
0.7.3 private BaseDanmaku findReuseableCache(finalBaseDanmaku refDanmaku,
final boolean strictMode,
final int maximumTimes) {
int slopPixel = 0;
if (!strictMode) {
slopPixel =mDisp.getSlopPixel() * 2;
}
final int finalSlopPixel = slopPixel;
IDanmakus.Consumer<BaseDanmaku, BaseDanmaku>consumer = new IDanmakus.Consumer<BaseDanmaku, BaseDanmaku>() {
int count = 0;
BaseDanmaku mResult;
@Override
public BaseDanmaku result() {
return mResult;
}
@Override
public int accept(BaseDanmakudanmaku) {
if (count++ >=maximumTimes) {
return ACTION_BREAK;
}
IDrawingCache<?>cache = danmaku.getDrawingCache();
if (cache == null ||cache.get() == null) {
return ACTION_CONTINUE;
}
if (danmaku.paintWidth ==refDanmaku.paintWidth
&&danmaku.paintHeight == refDanmaku.paintHeight
&&danmaku.underlineColor == refDanmaku.underlineColor
&&danmaku.borderColor == refDanmaku.borderColor
&&danmaku.textColor == refDanmaku.textColor
&&danmaku.text.equals(refDanmaku.text)
&&danmaku.tag == refDanmaku.tag) {
mResult = danmaku;
return ACTION_BREAK;
}
if (strictMode) {
return ACTION_CONTINUE;
}
if (!danmaku.isTimeOut()) {
return ACTION_BREAK;
}
if (cache.hasReferences()){
return ACTION_CONTINUE;
}
float widthGap =cache.width() - refDanmaku.paintWidth;
float heightGap = cache.height() -refDanmaku.paintHeight;
if (widthGap >= 0&& widthGap <= finalSlopPixel &&
heightGap >= 0&& heightGap <= finalSlopPixel) {
mResult = danmaku;
return ACTION_BREAK;
}
return ACTION_CONTINUE;
}
};
mCaches.forEach(consumer);
return consumer.result();
}
改变的核心还是:0.5.0中通过自定义的IDanmakuIterator遍历
0.7.3中通过forEach遍历。
0.5.0 无
0.7.3 新增
privatevoid preMeasure() {
// pre measure
IDanmakus danmakus = null;
try {
long begin =mTimer.currMillisecond;
long end = begin +mContext.mDanmakuFactory.MAX_DANMAKU_DURATION * 2;
danmakus =danmakuList.subnew(begin - mContext.mDanmakuFactory.MAX_DANMAKU_DURATION, end);
} catch (Exception e) {
}
if (danmakus == null ||danmakus.isEmpty()) {
return;
}
danmakus.forEach(newIDanmakus.DefaultConsumer<BaseDanmaku>() {
@Override
public int accept(BaseDanmakuitem) {
if (mPause ||mCancelFlag) {
returnACTION_BREAK;
}
if(!item.hasPassedFilter()) {
mContext.mDanmakuFilters.filter(item, 0, 0, null, true, mContext);
}
if (item.isFiltered()){
returnACTION_CONTINUE;
}
if (!item.isMeasured()){
item.measure(mDisp, true);
}
if (!item.isPrepared()){
item.prepare(mDisp,true);
}
return ACTION_CONTINUE;
}
});
}
0.7.3 中新增的preMeasure方法,预测量方法,在prepareCaches(final boolean repositioned)方法的第一句会调用,preMeasure中通forEach遍历danmakuList.subnew(begin - mContext.mDanmakuFactory.MAX_DANMAKU_DURATION, end)
0.5.0 private long prepareCaches(booleanrepositioned) {
long curr =mCacheTimer.currMillisecond;
long end = curr + mContext.mDanmakuFactory.MAX_DANMAKU_DURATION *mScreenSize;
IDanmakuIterator itr = danmakus.iterator();
BaseDanmaku item = null;
long consumingTime = 0;
int orderInScreen = 0;
int currScreenIndex = 0;
int sizeInScreen = danmakus.size();
// String message = "";
while(!mPause && !mCancelFlag) {
boolean hasNext = itr.hasNext();
if (!hasNext) {
// message = "breakat not hasNext";
break;
}
item = itr.next();
if(last.getActualTime() < mTimer.currMillisecond) {
// message = "breakat last.time < mTimer.currMillisecond";
break;
}
IDrawingCache<?>cache = item.getDrawingCache();
if(cache != null && cache.get() != null) {
continue;
}
if(repositioned == false && (item.isTimeOut() || !item.isOutside())) {
continue;
}
if(!item.hasPassedFilter()) {
mContext.mDanmakuFilters.filter(item,orderInScreen, sizeInScreen, null, true, mContext);
}
//Log.e("prepareCache",currScreenIndex+","+indexInScreen+"," +item.time+"skip:"+skip);
if(item.priority == 0 && item.isFiltered()) {
continue;
}
0.7.3 private long prepareCaches(final booleanrepositioned) {
preMeasure();
final long curr = mCacheTimer.currMillisecond;
final long end = curr +mContext.mDanmakuFactory.MAX_DANMAKU_DURATION * mScreenSize;
final int sizeInScreen =danmakus.size();
// String message = "";
danmakus.forEach(new IDanmakus.DefaultConsumer<BaseDanmaku>() {
int orderInScreen = 0;
int currScreenIndex = 0;
@Override
publicint accept(BaseDanmaku item) {
if(mPause || mCancelFlag) {
return ACTION_BREAK;
}
if(last.getActualTime() < mTimer.currMillisecond) {
return ACTION_BREAK;
}
IDrawingCache<?>cache = item.getDrawingCache();
if(cache != null && cache.get() != null) {
return ACTION_CONTINUE;
}
if(repositioned == false && (item.isTimeOut() || !item.isOutside())) {
return ACTION_CONTINUE;
}
if(!item.hasPassedFilter()) {
mContext.mDanmakuFilters.filter(item, orderInScreen, sizeInScreen,null, true, mContext);
}
//Log.e("prepareCache",currScreenIndex+","+indexInScreen+"," +item.time+"skip:"+skip);
if(item.priority == 0 && item.isFiltered()) {
returnACTION_CONTINUE;
}
不同0.7.3对于一些方法内的变量类型添加了final类型限制,并且0.5.0中遍历用的自定义的IDanmakuIterator,0.7.3用的是forEach()方法遍历。
DanmakuFilters
0.5.0 private final void removeTimeoutDanmakus(final IDanmakus danmakus,long limitTime) {
IDanmakuIterator it= danmakus.iterator();
long startTime =SystemClock.uptimeMillis();
while (it.hasNext()){
try {
BaseDanmaku item =it.next();
if (item.isTimeOut()) {
it.remove();
} else {
break;
}
} catch (Exception e) {
break;
}
if (SystemClock.uptimeMillis()- startTime > limitTime) {
break;
}
}
}
0.7.3 private final voidremoveTimeoutDanmakus(final IDanmakus danmakus, final long limitTime) {
danmakus.forEachSync(newIDanmakus.DefaultConsumer<BaseDanmaku>() {
long startTime =SystemClock.uptimeMillis();
@Override
public intaccept(BaseDanmaku item) {
try {
if(SystemClock.uptimeMillis() - startTime > limitTime) {
returnACTION_BREAK;
}
if (item.isTimeOut()) {
returnACTION_REMOVE;
} else {
returnACTION_BREAK;
}
} catch (Exception e) {
return ACTION_BREAK;
}
}
});
}
0.5.0移除超时弹幕用的是IDanmakuIterator遍历去移除,依次遍历
0.7.3 移除超时弹幕用的是danmakus.forEachSync()方法,其中forEachSync为接口IDanmakus新增的方法。
DrawHandler
0.5.0
public long getPausedPosition() {
return pausedPosition;
}
public void setPausedPosition(long pausedPosition) {
this.pausedPosition = pausedPosition;
}
public booleanismReady() {
return mReady;
}
public void setmReady(boolean mReady) {
this.mReady = mReady;
}
public Callback getmCallback() {
return mCallback;
}
public void setmCallback(CallbackmCallback) {
this.mCallback = mCallback;
}
public IDrawTask getDrawTask() {
return drawTask;
}
public void setDrawTask(IDrawTask drawTask){
this.drawTask = drawTask;
}
0.7.3 上述代码已经删除
0.5.0 privatevoid prepare(final Runnable runnable) {
@Override
public void onDanmakuAdd(BaseDanmaku danmaku) {
long delay =danmaku.getActualTime() - timer.currMillisecond;
if (delay > 0) {
sendEmptyMessageDelayed(NOTIFY_RENDERING, delay);
} else if (mInWaitingState) {
notifyRendering();
}
0.7.3private void prepare(final Runnable runnable) {
@Override
public void onDanmakuAdd(BaseDanmaku danmaku) {
if (danmaku.isTimeOut()) {
return;
}
long delay = danmaku.getActualTime() -getCurrentTime();
if (delay <mContext.mDanmakuFactory.MAX_DANMAKU_DURATION && (mInWaitingState ||mRenderingState.nothingRendered)) {
notifyRendering();
} else if (delay > 0 && delay <=mContext.mDanmakuFactory.MAX_DANMAKU_DURATION) {
sendEmptyMessageDelayed(NOTIFY_RENDERING, delay);
}
0.5.0 的填充弹幕逻辑是,如果delay大于0,则delay时间之后再填充,如果mInWaitingState为true则立即填充
0.7.3 的填充逻辑是如果delay小于弹幕的最大持续时间,并且mInWaitingState或者mRenderingState.nothingRendered为true,则立即填充。如果delay大于0并且小于弹幕工厂的最大持续时间,则delay时间之后再填充。
0.5.0 public void resume() {
sendEmptyMessage(DrawHandler.RESUME);
}
public void prepare() {
sendEmptyMessage(DrawHandler.PREPARE);
}
public void pause() {
syncTimerIfNeeded();
sendEmptyMessage(DrawHandler.PAUSE);
}
0.7.3 public void resume() {
removeMessages(DrawHandler.PAUSE);
sendEmptyMessage(DrawHandler.RESUME);
}
public void prepare() {
mReady = false;
sendEmptyMessage(DrawHandler.PREPARE);
}
public void pause() {
removeMessages(DrawHandler.RESUME);
syncTimerIfNeeded();
sendEmptyMessage(DrawHandler.PAUSE);
}
0.5.0 无
0.7.3新增了对应方法,例如在resume中增加了removeMessage(DrawHandler.PAUSE)。
0.5.0 public RenderingState draw(Canvas canvas) {
if (drawTask == null)
return mRenderingState;
if (!quitFlag && !mInWaitingState) {
AbsDanmakuSync danmakuSync =mContext.danmakuSync;
if (danmakuSync != null &&danmakuSync.getSyncState() == AbsDanmakuSync.SYNC_STATE_PLAYING) {
long fromTime =timer.currMillisecond;
long toTime =danmakuSync.getUptimeMillis();
long offset = toTime -fromTime;
if (Math.abs(offset) >danmakuSync.getThresholdTimeMills()) {
drawTask.requestSync(fromTime, toTime, offset);
timer.update(toTime);
mTimeBase =SystemClock.uptimeMillis() - toTime;
mRemainingTime = 0;
}
}
}
mDisp.setExtraData(canvas);
mRenderingState.set(drawTask.draw(mDisp));
recordRenderingTime();
return mRenderingState;
}
0.7.3 public RenderingState draw(Canvas canvas) {
if (drawTask == null)
return mRenderingState;
if (!mInWaitingState) {
AbsDanmakuSync danmakuSync =mContext.danmakuSync;
if (danmakuSync != null) {
do {
boolean isSyncPlayingState= danmakuSync.isSyncPlayingState();
if (!isSyncPlayingState&& !quitFlag) {
break;
}
int syncState =danmakuSync.getSyncState();
if (syncState ==AbsDanmakuSync.SYNC_STATE_PLAYING) {
long fromTime =timer.currMillisecond;
long toTime =danmakuSync.getUptimeMillis();
long offset = toTime -fromTime;
if (Math.abs(offset)> danmakuSync.getThresholdTimeMills()) {
if (isSyncPlayingState&& quitFlag) {
resume();
}
drawTask.requestSync(fromTime, toTime, offset);
timer.update(toTime);
mTimeBase =SystemClock.uptimeMillis() - toTime;
mRemainingTime = 0;
}
} else if (syncState ==AbsDanmakuSync.SYNC_STATE_HALT) {
if (isSyncPlayingState&& !quitFlag) {
pause();
}
}
} while (false);
}
}
mDisp.setExtraData(canvas);
mRenderingState.set(drawTask.draw(mDisp));
recordRenderingTime();
return mRenderingState;
}
0.5.0 无
0.7.3 在判断条件中去掉了字段!quitFlag,新加了danmakuSync字段的if判断,并且黄色代码中,新的版本用do{}while包住了执行代码,加了if(!isSyncPlayingState && !quitFlag),如果符合停止条件则break循环,增加了if (isSyncPlayingState && quitFlag) {resume();}代码等。
0.5.0 private synchronized longgetAverageRenderingTime() {
int frames = mDrawTimes.size();
if (frames <= 0)
return 0;
long dtime = mDrawTimes.getLast() -mDrawTimes.getFirst();
return dtime / frames;
}
0.7.3private synchronized long getAverageRenderingTime() {
int frames = mDrawTimes.size();
if(frames <= 0)
return 0;
Long first = mDrawTimes.peekFirst();
Long last = mDrawTimes.peekLast();
if (first == null || last == null) {
return 0;
}
long dtime = last - first;
return dtime / frames;
}
0.5.0和0.7.3中dtime的计算方式有所改变。
DrawTask
0.5.0 public AbsDisplayergetmDisp() {
return mDisp;
}
public IDanmakus getDanmakuList() {
return danmakuList;
}
public void setDanmakuList(IDanmakusdanmakuList) {
this.danmakuList = danmakuList;
}
public DanmakuTimer getmTimer() {
return mTimer;
}
public void setmTimer(DanmakuTimer mTimer) {
this.mTimer = mTimer;
}
public BaseDanmaku getmLastDanmaku() {
return mLastDanmaku;
}
public void setmLastDanmaku(BaseDanmakumLastDanmaku) {
this.mLastDanmaku = mLastDanmaku;
}
0.7.3 无
在0.7.3版本中,上述代码被移除。
0.5.0 @Override
public void invalidateDanmaku(BaseDanmaku item, boolean remeasure) {
mContext.getDisplayer().getCacheStuffer().clearCache(item);
if (remeasure) {
item.paintWidth = -1;
item.paintHeight = -1;
}
}
0.7.3 @Override
public void invalidateDanmaku(BaseDanmaku item, boolean remeasure) {
mContext.getDisplayer().getCacheStuffer().clearCache(item);
item.requestFlags|= BaseDanmaku.FLAG_REQUEST_INVALIDATE;
if (remeasure) {
item.paintWidth = -1;
item.paintHeight = -1;
item.requestFlags|= BaseDanmaku.FLAG_REQUEST_REMEASURE;
item.measureResetFlag++;
}
}
0.7.3中 添加了invalidateDanmaku()方法的变量赋值,涉及到requestFlags和measureResetFlag两个变量。
0.5.0 protected voidloadDanmakus(BaseDanmakuParser parser) {
danmakuList =parser.setConfig(mContext).setDisplayer(mDisp).setTimer(mTimer).getDanmakus();
if (danmakuList !=null && !danmakuList.isEmpty()) {
if(danmakuList.first().flags == null) {
IDanmakuIteratorit = danmakuList.iterator();
while(it.hasNext()) {
BaseDanmakuitem = it.next();
if (item != null) {
item.flags = mContext.mGlobalFlagValues;
}
}
}
}
mContext.mGlobalFlagValues.resetAll();
if(danmakuList != null) {
mLastDanmaku = danmakuList.last();
}
}
0.7.3 protected voidloadDanmakus(BaseDanmakuParser parser) {
danmakuList =parser.setConfig(mContext).setDisplayer(mDisp).setTimer(mTimer).setListener(newBaseDanmakuParser.Listener() {
@Override
public voidonDanmakuAdd(BaseDanmaku danmaku) {
if (mTaskListener!= null) {
mTaskListener.onDanmakuAdd(danmaku);
}
}
}).getDanmakus();
mContext.mGlobalFlagValues.resetAll();
if(danmakuList != null) {
mLastDanmaku = danmakuList.last();
}
}
0.5.0 通过IDanmakuIterator遍历danmakuList去依次设置BaseDanmaku.item值
0.7.3 通过通过BaseDanmakuParser设置接口回调,回调方法onDanmakuAdd()方法
其他的不同之处都是,0.5.0通过Iterator去遍历,0.7.3通过forEach去遍历。
IDanmakuView
0.5.0 public interface OnDanmakuClickListener {
/**
*
* @param latest the latest one is clicked
*/
void onDanmakuClick(BaseDanmaku latest);
/**
*
* @param danmakus all to be clicked
*/
void onDanmakuClick(IDanmakus danmakus);
}
0.7.3 public interfaceOnDanmakuClickListener {
/**
* @param danmakus all to be clicked, this value may be empty;
* danmakus.last() is the latest danmakuwhich may be null;
* @return True if the event was handled, false otherwise.
*/
boolean onDanmakuClick(IDanmakus danmakus);
boolean onViewClick(IDanmakuView view);
}
0.5.0 和0.7.3对于OnDanmakuClickListener的回调方法的名称和参数都有改变。
AndroidDisplayer
0.5.0无
0.7.3新增
public voidapplyPaintConfig(BaseDanmaku danmaku, Paint paint, boolean stroke) {
if (danmaku.getType() == BaseDanmaku.TYPE_SPECIAL) {
paint.setAlpha(danmaku.getAlpha());
}
}
private float locationZ;
public int draw(BaseDanmaku danmaku) {
if (canvas !=null) {
if (!cacheDrawn) {
if (alphaPaint != null) {
mDisplayConfig.PAINT_DUPLICATE.setAlpha(alphaPaint.getAlpha());
0.7.3针对特殊弹幕的透明度,新增了一个配置方法,在Draw方法中也添加了透明度的设置函数,并且新增了locationZ变量,我感觉是为了绘制搞基弹幕准备的。
0.5.0 private int saveCanvas(BaseDanmaku danmaku, Canvas canvas, floatleft, float top) {
camera.save();
camera.rotateY(-danmaku.rotationY);
camera.rotateZ(-danmaku.rotationZ);
camera.getMatrix(matrix);
matrix.preTranslate(-left,-top);
matrix.postTranslate(left, top);
camera.restore();
int count = canvas.save();
canvas.concat(matrix);
return count;
}
0.7.3 private int saveCanvas(BaseDanmaku danmaku, Canvas canvas, floatleft, float top) {
camera.save();
if (locationZ !=0&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
camera.setLocation(0,0, locationZ);
}
camera.rotateY(-danmaku.rotationY);
camera.rotateZ(-danmaku.rotationZ);
camera.getMatrix(matrix);
// matrix.preTranslate(-left, -top);
matrix.postTranslate(left , top);
camera.restore();
int count = canvas.save();
canvas.concat(matrix);
return count;
}
0.5.0
0.7.3 增加了根据locationZ等变量设置camera.setLocation()方法,去掉了matrix.preTranslate()方法。
0.5.0无
0.7.3新增
@Override
public voidprepare(BaseDanmaku danmaku, boolean fromWorkerThread) {
if (sStuffer != null) {
sStuffer.prepare(danmaku, fromWorkerThread);
}
}
@Override
public void setSize(int width, int height) {
this.width = width;
this.height = height;
this.locationZ =(float) (width / 2f / Math.tan((Math.PI / 180) * (55f / 2f)));
}
0.5.0
0.7.3 新增了prepare重写方法,并且增加了根据locationZ设置弹幕位置的变量。
BaseCacheStuffer
0.5.0 无
0.7.3 新增
public void prepare(BaseDanmaku danmaku, boolean fromWorkerThread) {
if (mProxy != null) {
mProxy.prepareDrawing(danmaku, fromWorkerThread);
}
}
public boolean drawCache(BaseDanmakudanmaku, Canvas canvas, float left, float top, Paint alphaPaint, TextPaint paint) {
IDrawingCache<?>cache = danmaku.getDrawingCache();
if (cache != null) {
DrawingCacheHolderholder = (DrawingCacheHolder) cache.get();
if (holder != null) {
returnholder.draw(canvas, left, top, alphaPaint);
}
}
return false;
}
0.7.3 新增了prepare方法,此方法在AndroidDisplayer中有调用,在drawCache中,添加了具体的缓存绘制方法。
DanmakuFactory
0.5.0
private voidupdateSpecialDanmakusDate(float scaleX, float scaleY) {
IDanmakus list = sSpecialDanmakus;
IDanmakuIterator it =list.iterator();
while (it.hasNext()) {
SpecialDanmaku speicalDanmaku = (SpecialDanmaku) it.next();
fillTranslationData(speicalDanmaku, speicalDanmaku.beginX,speicalDanmaku.beginY,
speicalDanmaku.endX,speicalDanmaku.endY, speicalDanmaku.translationDuration,
speicalDanmaku.translationStartDelay, scaleX, scaleY);
LinePath[] linePaths = speicalDanmaku.linePaths;
if (linePaths != null && linePaths.length > 0) {
int length = linePaths.length;
float[][] points = newfloat[length + 1][2];
for (int j = 0; j < length;j++) {
points[j] =linePaths[j].getBeginPoint();
points[j + 1] =linePaths[j].getEndPoint();
}
fillLinePathData(speicalDanmaku, points, scaleX, scaleY);
}
}
}
0.7.3
private void updateSpecialDanmakusDate(final float scaleX, final floatscaleY) {
IDanmakus list = sSpecialDanmakus;
list.forEachSync(newIDanmakus.DefaultConsumer<BaseDanmaku>() {
@Override
public intaccept(BaseDanmaku danmaku) {
SpecialDanmakuspeicalDanmaku = (SpecialDanmaku) danmaku;
fillTranslationData(speicalDanmaku, speicalDanmaku.beginX,speicalDanmaku.beginY,
speicalDanmaku.endX,speicalDanmaku.endY, speicalDanmaku.translationDuration,
speicalDanmaku.translationStartDelay, scaleX, scaleY);
LinePath[] linePaths =speicalDanmaku.linePaths;
if (linePaths != null&& linePaths.length > 0) {
int length = linePaths.length;
float[][] points = newfloat[length + 1][2];
for (int j = 0; j <length; j++) {
points[j] =linePaths[j].getBeginPoint();
points[j + 1] =linePaths[j].getEndPoint();
}
fillLinePathData(speicalDanmaku, points, scaleX, scaleY);
}
return ACTION_CONTINUE;
}
});
}
0.5.0 采用Iterator的遍历方式
0.7.3 采用forEach的遍历方式。
Danmakus
0.5.0 删除:
public static final int ST_BY_TIME = 0;
public static final int ST_BY_YPOS = 1;
public static final int ST_BY_YPOS_DESC = 2;
/**
* this type is used to iterate/remove/insert elements, not supportsub/subnew
*/
public static finalint ST_BY_LIST = 4;
private DanmakuIterator iterator;
private class DanmakuIterator implementsIDanmakuIterator {
private Collection<BaseDanmaku> mData;
private Iterator<BaseDanmaku> it;
private boolean mIteratorUsed;
public DanmakuIterator(Collection<BaseDanmaku> datas) {
setDatas(datas);
}
public synchronized void reset() {
if (!mIteratorUsed && it != null) {
return;
}
if (mData != null && mSize > 0) {
it = mData.iterator();
} else {
it = null;
}
mIteratorUsed = false;
}
public synchronized void setDatas(Collection<BaseDanmaku> datas) {
if (mData != datas) {
mIteratorUsed = false;
it = null;
}
mData = datas;
}
@Override
public synchronized BaseDanmaku next() {
mIteratorUsed = true;
return it != null ? it.next() : null;
}
@Override
public synchronized boolean hasNext() {
return it != null && it.hasNext();
}
@Override
public synchronized void remove() {
mIteratorUsed = true;
if (it != null) {
it.remove();
mSize--;
}
}
}
private class BaseComparator implements Comparator<BaseDanmaku> {
protected boolean mDuplicateMergingEnable;
public BaseComparator(booleanduplicateMergingEnabled) {
setDuplicateMergingEnabled(duplicateMergingEnabled);
}
public void setDuplicateMergingEnabled(boolean enable) {
mDuplicateMergingEnable = enable;
}
@Override
public int compare(BaseDanmaku obj1, BaseDanmaku obj2) {
if (mDuplicateMergingEnable && DanmakuUtils.isDuplicate(obj1,obj2)) {
return 0;
}
return DanmakuUtils.compare(obj1, obj2);
}
}
private class TimeComparator extends BaseComparator {
public TimeComparator(boolean duplicateMergingEnabled) {
super(duplicateMergingEnabled);
}
@Override
public int compare(BaseDanmaku obj1, BaseDanmaku obj2) {
return super.compare(obj1, obj2);
}
}
private class YPosComparator extends BaseComparator {
public YPosComparator(boolean duplicateMergingEnabled) {
super(duplicateMergingEnabled);
}
@Override
public int compare(BaseDanmaku obj1, BaseDanmaku obj2) {
if (mDuplicateMergingEnable && DanmakuUtils.isDuplicate(obj1,obj2)) {
return 0;
}
return Float.compare(obj1.getTop(), obj2.getTop());
}
}
private class YPosDescComparator extends BaseComparator {
public YPosDescComparator(boolean duplicateMergingEnabled) {
super(duplicateMergingEnabled);
}
@Override
public int compare(BaseDanmaku obj1, BaseDanmaku obj2) {
if (mDuplicateMergingEnable && DanmakuUtils.isDuplicate(obj1,obj2)) {
return 0;
}
return Float.compare(obj2.getTop(), obj1.getTop());
}
0.7.3 新增:
@Override
public Collection<BaseDanmaku> getCollection() {
return this.items;
}
@Override
public void forEachSync(Consumer<? super BaseDanmaku, ?> consumer){
synchronized (this.mLockObject) {
forEach(consumer);
}
}
@Override
public void forEach(Consumer<? super BaseDanmaku, ?> consumer) {
consumer.before();
Iterator<BaseDanmaku> it = items.iterator();
while (it.hasNext()) {
BaseDanmaku next = it.next();
if (next == null) {
continue;
}
int action = consumer.accept(next);
if (action == DefaultConsumer.ACTION_BREAK) {
break;
} else if (action == DefaultConsumer.ACTION_REMOVE) {
it.remove();
} else if (action == DefaultConsumer.ACTION_REMOVE_AND_BREAK) {
it.remove();
break;
}
}
consumer.after();
}
@Override
public Object obtainSynchronizer() {
return mLockObject;
}
0.7.3版本中Danmakus类主要的改变是去掉了之前通过自定义的Iterator遍历的方式,而是改用forEach的方式来遍历。其中,forEach内部的实现过程也是通过Iterator,只不过这样写更简洁,封装了一下。
SimpleTextCacheStuffer
0.5.0删除
if (mProxy != null) {
mProxy.prepareDrawing(danmaku, fromWorkerThread);
}
@Override
public boolean drawCache(BaseDanmaku danmaku, Canvas canvas, float left,float top, Paint alphaPaint, TextPaint paint) {
IDrawingCache<?> cache = danmaku.getDrawingCache();
if (cache != null) {
DrawingCacheHolder holder = (DrawingCacheHolder) cache.get();
if (holder != null) {
return holder.draw(canvas,left, top, alphaPaint);
}
}
return false;
}
0.7.3无
0.5.0的drawCache()方法在SimpleTextCacheStuffer中被移除,该方法被迁移到了BaseCacheStuffer中实现。
ViewCacheStuffer
该类为0.7.3版本中新增的类,该类没啥作用,只是在sample demo方法中的UglyViewCacheStufferSampleActivity测试页面中使用过,该类填充缓存使得弹幕内容都加上了图标,感觉是为了测试使用的。
AbsDanmakuSync
0.5.0 无
0.7.3 新增
/**
* synchronize pause/resume state with outside playback
* @return
*/
public boolean isSyncPlayingState() {
return false;
}
0.7.3中增加这个方法,为了同步播放页面的暂停/继续状态和手机的back键的状态。
BaseDanmaku
0.5.0 无
0.7.3新增
/**
* 重置位 prepare
*/
public int prepareResetFlag = -1;
/**
public boolean isPrepared() {
return this.prepareResetFlag == flags.PREPARE_RESET_FLAG;
}
public void prepare(IDisplayer displayer, boolean fromWorkerThread) {
displayer.prepare(this, fromWorkerThread);
this.prepareResetFlag = flags.PREPARE_RESET_FLAG;
}
0.7.3 这两个函数感觉是用来标识当前的弹幕是否准备完成,是否可以在屏幕呈现。
GlobalFlagValues
0.5.0 无
0.7.3 新增
public int PREPARE_RESET_FLAG = 0;
public void resetAll() {
VISIBLE_RESET_FLAG = 0;
MEASURE_RESET_FLAG = 0;
FILTER_RESET_FLAG = 0;
FIRST_SHOWN_RESET_FLAG = 0;
SYNC_TIME_OFFSET_RESET_FLAG= 0;
PREPARE_RESET_FLAG = 0;
}
public void updatePrepareFlag() {
PREPARE_RESET_FLAG++;
}
0.7.3 新增了准备状态的标志位,感觉是为了当弹幕准备完成时,做相应的操作。
IDanmakus
0.5.0
0.7.3 新增
abstract class Consumer<Progress,Result> {
public static final int ACTION_CONTINUE = 0;
public static final int ACTION_BREAK = 1;
public static final int ACTION_REMOVE = 2;
public static final int ACTION_REMOVE_AND_BREAK = 3;
/**
* Performs this operation on the given argument.
*
* @param t the input argument
* @return next action of the loop
*
* @see #ACTION_CONTINUE
* @see #ACTION_BREAK
* @see #ACTION_REMOVE
*/
public abstract int accept(Progress t);
public void before() {
}
public void after() {
}
public Result result() {
return null;
}
}
abstract class DefaultConsumer<Progress> extendsConsumer<Progress, Void> {
}
int ST_BY_TIME = 0;
int ST_BY_YPOS = 1;
intST_BY_YPOS_DESC = 2;
/**
* this type is used to iterate/remove/insert elements, not supportsub/subnew
*/
int ST_BY_LIST =4;
boolean contains(BaseDanmaku item);
boolean isEmpty();
void setSubItemsDuplicateMergingEnabled(boolean enable);
Collection<BaseDanmaku> getCollection();
void forEachSync(Consumer<? super BaseDanmaku, ?> consumer);
void forEach(Consumer<? super BaseDanmaku, ?> consumer);
Object obtainSynchronizer();
class BaseComparator implements Comparator<BaseDanmaku> {
protected boolean mDuplicateMergingEnable;
public BaseComparator(boolean duplicateMergingEnabled) {
setDuplicateMergingEnabled(duplicateMergingEnabled);
}
public void setDuplicateMergingEnabled(boolean enable) {
mDuplicateMergingEnable = enable;
}
@Override
public int compare(BaseDanmaku obj1, BaseDanmaku obj2) {
if (mDuplicateMergingEnable && DanmakuUtils.isDuplicate(obj1,obj2)) {
return 0;
}
return DanmakuUtils.compare(obj1, obj2);
}
}
class TimeComparator extends BaseComparator {
public TimeComparator(boolean duplicateMergingEnabled) {
super(duplicateMergingEnabled);
}
@Override
public int compare(BaseDanmaku obj1, BaseDanmaku obj2) {
return super.compare(obj1, obj2);
}
}
class YPosComparator extends BaseComparator {
public YPosComparator(boolean duplicateMergingEnabled) {
super(duplicateMergingEnabled);
}
@Override
public int compare(BaseDanmaku obj1, BaseDanmaku obj2) {
if (mDuplicateMergingEnable && DanmakuUtils.isDuplicate(obj1,obj2)) {
return 0;
}
return Float.compare(obj1.getTop(), obj2.getTop());
}
}
class YPosDescComparator extends BaseComparator {
public YPosDescComparator(boolean duplicateMergingEnabled) {
super(duplicateMergingEnabled);
}
@Override
public int compare(BaseDanmaku obj1, BaseDanmaku obj2) {
if (mDuplicateMergingEnable && DanmakuUtils.isDuplicate(obj1,obj2)) {
return 0;
}
return Float.compare(obj2.getTop(), obj1.getTop());
}
}
0.7.3 新增的Consumer为了处理弹幕的RESUME、PAUSE等事件,新增的各种Comparator,为了处理合并重复弹幕,例如合并同一时间的弹幕,合并相同内容的弹幕,等。
Idisplayer
0.5.0
0.7.3 新增
void prepare(BaseDanmaku danmaku, booleanfromWorkerThread);
0.7.3 通知弹幕是否准备完成
BaseDanmakuParser
0.5.0
0.7.3 新增
public interface Listener {
void onDanmakuAdd(BaseDanmaku danmaku);
}
protected Listener mListener;
public IDisplayer getDisplayer(){
return mDisp;
}
public BaseDanmakuParser setListener(Listener listener) {
mListener = listener;
return this;
}
删除
public IDisplayer getDisplayer(){
return mDisp;
}
0.7.3 新增了新的弹幕添加的回调方法,获取当前弹幕的AndroidDisplayer,设置当前弹幕的Parser.
DanmakuRenderer
0.5.0 修改
@Override
public void draw(IDisplayer disp, IDanmakus danmakus, longstartRenderTime, RenderingState renderingState) {
mStartTimer = renderingState.timer;
BaseDanmaku drawItem = null;
IDanmakuIterator itr = danmakus.iterator();
while (itr.hasNext()) {
drawItem = itr.next();
if (drawItem.isTimeOut()) {
itr.remove();
disp.recycle(drawItem);
continue;
}
if (!renderingState.isRunningDanmakus && drawItem.isOffset()) {
itr.remove();
continue;
}
if (!drawItem.hasPassedFilter()) {
mContext.mDanmakuFilters.filter(drawItem,renderingState.indexInScreen, renderingState.totalSizeInScreen,renderingState.timer, false, mContext);
}
if (drawItem.getActualTime() < startRenderTime
|| (drawItem.priority == 0&& drawItem.isFiltered())) {
continue;
}
if (drawItem.isLate()) {
IDrawingCache<?> cache =drawItem.getDrawingCache();
if (mCacheManager != null&& (cache == null || cache.get() == null)) {
mCacheManager.addDanmaku(drawItem);
}
break;
}
if (drawItem.getType() == BaseDanmaku.TYPE_SCROLL_RL){
// 同屏弹幕密度只对滚动弹幕有效
renderingState.indexInScreen++;
}
// measure
if (!drawItem.isMeasured()) {
drawItem.measure(disp, false);
}
// layout
mDanmakusRetainer.fix(drawItem, disp, mVerifier);
// draw
if (drawItem.isShown()) {
if (drawItem.lines == null&& drawItem.getBottom() > disp.getHeight()) {
continue; // skip bottom outside danmaku
}
int renderingType =drawItem.draw(disp);
if(renderingType ==IRenderer.CACHE_RENDERING) {
renderingState.cacheHitCount++;
} else if(renderingType ==IRenderer.TEXT_RENDERING) {
renderingState.cacheMissCount++;
if (mCacheManager != null){
mCacheManager.addDanmaku(drawItem);
}
}
renderingState.addCount(drawItem.getType(), 1);
renderingState.addTotalCount(1);
renderingState.appendToRunningDanmakus(drawItem);
if (mOnDanmakuShownListener !=null
&&drawItem.firstShownFlag != mContext.mGlobalFlagValues.FIRST_SHOWN_RESET_FLAG) {
drawItem.firstShownFlag= mContext.mGlobalFlagValues.FIRST_SHOWN_RESET_FLAG;
mOnDanmakuShownListener.onDanmakuShown(drawItem);
}
}
}
renderingState.lastDanmaku = drawItem;
}
0.7.3 修改
private class Consumer extendsIDanmakus.DefaultConsumer<BaseDanmaku> {
private BaseDanmaku lastItem;
public IDisplayer disp;
public RenderingState renderingState;
public long startRenderTime;
@Override
public int accept(BaseDanmaku drawItem) {
lastItem = drawItem;
if (drawItem.isTimeOut()) {
disp.recycle(drawItem);
return ACTION_CONTINUE;
}
if (!renderingState.isRunningDanmakus && drawItem.isOffset()) {
return ACTION_REMOVE;
}
if (!drawItem.hasPassedFilter()) {
mContext.mDanmakuFilters.filter(drawItem, renderingState.indexInScreen,renderingState.totalSizeInScreen, renderingState.timer, false, mContext);
}
if (drawItem.getActualTime() < startRenderTime
|| (drawItem.priority == 0&& drawItem.isFiltered())) {
return ACTION_CONTINUE;
}
if (drawItem.isLate()) {
IDrawingCache<?> cache =drawItem.getDrawingCache();
if (mCacheManager != null&& (cache == null || cache.get() == null)) {
mCacheManager.addDanmaku(drawItem);
}
return ACTION_BREAK;
}
if (drawItem.getType() == BaseDanmaku.TYPE_SCROLL_RL) {
// 同屏弹幕密度只对滚动弹幕有效
renderingState.indexInScreen++;
}
// measure
if (!drawItem.isMeasured()) {
drawItem.measure(disp, false);
}
// notify prepare drawing
if (!drawItem.isPrepared()) {
drawItem.prepare(disp, false);
}
// layout
mDanmakusRetainer.fix(drawItem, disp, mVerifier);
// draw
if (drawItem.isShown()) {
if (drawItem.lines == null&& drawItem.getBottom() > disp.getHeight()) {
returnACTION_CONTINUE; // skip bottomoutside danmaku
}
int renderingType =drawItem.draw(disp);
if (renderingType ==IRenderer.CACHE_RENDERING) {
renderingState.cacheHitCount++;
} else if (renderingType ==IRenderer.TEXT_RENDERING) {
renderingState.cacheMissCount++;
if (mCacheManager != null){
mCacheManager.addDanmaku(drawItem);
}
}
renderingState.addCount(drawItem.getType(), 1);
renderingState.addTotalCount(1);
renderingState.appendToRunningDanmakus(drawItem);
if (mOnDanmakuShownListener !=null
&& drawItem.firstShownFlag !=mContext.mGlobalFlagValues.FIRST_SHOWN_RESET_FLAG) {
drawItem.firstShownFlag =mContext.mGlobalFlagValues.FIRST_SHOWN_RESET_FLAG;
mOnDanmakuShownListener.onDanmakuShown(drawItem);
}
}
return ACTION_CONTINUE;
}
@Override
public void after() {
renderingState.lastDanmaku = lastItem;
super.after();
}
}
0.7.3中将draw()方法中的具体实现,合并到方法private class Consumer extendsIDanmakus.DefaultConsumer<BaseDanmaku>中去实现,将0.5.0的自定义Iterator通过0.7.3的forEach代替,并回调类Consumer的方法来代替draw()方法。
DanmakusRetainer
0.5.0
0.7.3 新增
private static class AlignBottomRetainer extends FTDanmakusRetainer {
protected class RetainerConsumer extendsIDanmakus.Consumer<BaseDanmaku, RetainerState> {
public IDisplayer disp;
int lines = 0;
public BaseDanmaku removeItem = null, firstItem = null, drawItem = null;
boolean willHit = false;
float topPos;
@Override
public void before() {
lines = 0;
removeItem = firstItem = null;
willHit = false;
}
@Override
public int accept(BaseDanmaku item) {
if (mCancelFixingFlag) {
return ACTION_BREAK;
}
lines++;
if (item == drawItem) {
removeItem = null;
willHit = false;
return ACTION_BREAK;
}
if (firstItem == null) {
firstItem = item;
if (firstItem.getBottom()!= disp.getHeight()) {
return ACTION_BREAK;
}
}
if (topPos < 0) {
removeItem = null;
return ACTION_BREAK;
}
// 检查碰撞
willHit = DanmakuUtils.willHitInDuration(disp,item, drawItem,
drawItem.getDuration(),drawItem.getTimer().currMillisecond);
if (!willHit) {
removeItem = item;
// topPos =item.getBottom() - drawItem.paintHeight;
return ACTION_BREAK;
}
topPos = item.getTop() -drawItem.paintHeight;
return ACTION_CONTINUE;
}
@Override
public RetainerState result() {
RetainerState retainerState =new RetainerState();
retainerState.lines =this.lines;
retainerState.firstItem =this.firstItem;
retainerState.removeItem =this.removeItem;
retainerState.willHit =this.willHit;
return retainerState;
}
}
private static class AlignTopRetainer implements IDanmakusRetainer {
protected class RetainerConsumer extendsIDanmakus.Consumer<BaseDanmaku, RetainerState> {
public IDisplayer disp;
int lines = 0;
public BaseDanmaku insertItem = null, firstItem = null, lastItem = null,minRightRow = null, drawItem = null;
boolean overwriteInsert = false;
boolean shown = false;
boolean willHit = false;
@Override
public void before() {
lines = 0;
insertItem = firstItem =lastItem = minRightRow = null;
overwriteInsert = shown =willHit = false;
}
@Override
public int accept(BaseDanmaku item) {
if (mCancelFixingFlag) {
return ACTION_BREAK;
}
lines++;
if(item == drawItem){
insertItem = item;
lastItem = null;
shown = true;
willHit = false;
return ACTION_BREAK;
}
if (firstItem == null)
firstItem = item;
if (drawItem.paintHeight +item.getTop() > disp.getHeight()) {
overwriteInsert = true;
return ACTION_BREAK;
}
if (minRightRow == null) {
minRightRow = item;
} else {
if (minRightRow.getRight()>= item.getRight()) {
minRightRow = item;
}
}
// 检查碰撞
willHit =DanmakuUtils.willHitInDuration(disp, item, drawItem,
drawItem.getDuration(),drawItem.getTimer().currMillisecond);
if (!willHit) {
insertItem = item;
return ACTION_BREAK;
}
lastItem = item;
return ACTION_CONTINUE;
}
@Override
public RetainerState result() {
RetainerState retainerState =new RetainerState();
retainerState.lines =this.lines;
retainerState.firstItem =this.firstItem;
retainerState.insertItem =this.insertItem;
retainerState.lastItem =this.lastItem;
retainerState.minRightRow = this.minRightRow;
retainerState.overwriteInsert =this.overwriteInsert;
retainerState.shown =this.shown;
retainerState.willHit =this.willHit;
return retainerState;
}
}
0.7.3 首先关于方法AlignTopRetainer()和AlignBottomRetainer()都增加了具体的实现代码,将0.5.0中的IDanmakuIterator通过mVisibleDanmakus.forEachSync(mConsumer)代替,0.7.3将0.5.0的一些方法过程进行了封装。
DanmakuSurfaceView
0.5.0 @Override
public boolean onTouchEvent(MotionEvent event) {
if (null != mTouchHelper) {
mTouchHelper.onTouchEvent(event);
}
return super.onTouchEvent(event);
}
0.7.3 @Override
public boolean onTouchEvent(MotionEvent event) {
boolean isEventConsumed =mTouchHelper.onTouchEvent(event);
if (!isEventConsumed) {
return super.onTouchEvent(event);
}
return isEventConsumed;
}
删除代码:
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
}
@Override
public DrawHandler getHandler() {
return handler;
}
public void setHandler(DrawHandler handler) {
this.handler = handler;
}
0.7.3对于onTouchEvent()方法进行了重写,其逻辑为通过变量isEventConsumed来表明该touch事件是否被消费,如果没有被消费则调用super.onTouchEvent(event);,如果被消费了则返回true。
DanmakuTouchHelper
0.5.0
public boolean onTouchEvent(MotionEventevent) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
IDanmakus clickDanmakus = touchHitDanmaku(event.getX(),event.getY());
BaseDanmaku newestDanmaku =null;
if (null != clickDanmakus&& !clickDanmakus.isEmpty()) {
performClick(clickDanmakus);
newestDanmaku =fetchLatestOne(clickDanmakus);
}
if (null != newestDanmaku) {
performClickWithlatest(newestDanmaku);
}
break;
default:
break;
}
return false;
}
0.7.3
public boolean onTouchEvent(MotionEvent event) {
return mTouchDelegate.onTouchEvent(event);
}
private final android.view.GestureDetector.OnGestureListenermOnGestureListener = new GestureDetector.SimpleOnGestureListener(){
@Override
public boolean onDown(MotionEvent event) {
if(danmakuView != null) {
IDanmakuView.OnDanmakuClickListener onDanmakuClickListener =danmakuView.getOnDanmakuClickListener();
if (onDanmakuClickListener != null) {
return true;
}
}
return false;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent event) {
IDanmakus clickDanmakus = touchHitDanmaku(event.getX(), event.getY());
boolean isEventConsumed = false;
if (null != clickDanmakus && !clickDanmakus.isEmpty()) {
isEventConsumed =performDanmakuClick(clickDanmakus);
}
if (!isEventConsumed) {
isEventConsumed =performViewClick();
}
return isEventConsumed;
}
};
0.7.3更改了用户点击事件的处理方式,0.5.0直接处理用户的点击事件,在onTouchEvent()方法中执行了点击事件处理。在0.7.3中通过new出GestureDetector的实例,并回调其onDown()方法和onSingleTapConfirmed()方法,来处理用户的点击事件。