Idea:??
音乐时光??
骑着车,戴着耳机,播放列表里有几首歌。
突然,很想听《且听风吟》,但是不想掏出手机,于是一路双击耳机播放键切歌。
emmm,下面是切过的歌:
第几次 | 随机到的音乐 | 停留的时间 |
---|---|---|
1 | Love Story | 2s |
2 | 东风破 | 3s |
3 | Refrain | 1s |
4 | 东风破 | 2s |
5 | Valder Fields | 2s |
6 | Love Story | 1s |
7 | My Soul | 3s |
8 | 白金ディスコ | 1s |
9 | Refrain | 3s |
... | ... | ... |
16 | 且听风吟 | 3min |
What?一共才几首歌,而我切了十多次才随机到自己想要的!
有些歌明明已经被切掉了,为什么马上又随机到?不够聪明诶。
那么,在监听到用户正在切歌时,可不可以直接跳过刚刚已经切过的歌?
当然是可行的。于是在RandomPicker基础上实现了CutMode。进入切歌模式后,切过的歌将不会再次出现,除非一轮已经切完。
Demo
如何使用
快速开始:
// 指定列表有n首歌,初始比重为1.
mRandomPicker = new RandomPicker(n, 1);
// 进入切歌模式。
mRandomPicker.enterCutMode();
// 随机获取下一首
int nextPos = mRandomPicker.next();
...
// 退出切歌模式
mRandomPicker.exitCutMode();
更多方法:
// 更默认的比重计算器
mRandomPicker.setCalculator(new Calculator() {
@Override
public int calculateNextWeight(int currentWeight, int originWeight) {
return (currentWeight + 1) * originWeight;
}
});
// 改变某个item的初始比重
mRandomPicker.changeOriginWeight(0, 3);
// 指定下次随机到的数
mRandomPicker.setNextPick(3);
//添加一个item至尾部,并为其赋值初始比重
mRandomPicker.add(2);
源码
GitHub: XunMengWinter/RandomPicker
下面贴出关键代码:
/*执行随机算法*/
private int randomPick() {
// 若列表长度小于2,则下一次位置必为0.
if (mCurrentWeightList.size() < 2) {
return 0;
}
int nextPos = 0;
// 算出下一次选中的位置
if (mNextPickPosition != null) {
nextPos = mNextPickPosition;
mNextPickPosition = null;
} else {
int allWeight = 0;
for (int i = 0; i < mCurrentWeightList.size(); i++) {
allWeight += mCurrentWeightList.get(i);
}
if (allWeight <= 0) {
//TODO avoid this situation.
allWeight = Integer.MAX_VALUE;
//Log.e(TAG, "...");
}
int nextPosInWeight = mRandom.nextInt(allWeight);
int currentWeight = 0;
for (int i = 0; i < mCurrentWeightList.size(); i++) {
currentWeight += mCurrentWeightList.get(i);
if (currentWeight > nextPosInWeight) {
nextPos = i;
break;
}
}
}
// 预先算好下一次的比重
for (int i = 0; i < mCurrentWeightList.size(); i++) {
if (isCutMode()) {
if (mCutOutSet.contains(i)) {
continue;
}
}
int weight = calculateWeight(mCurrentWeightList.get(i), mOriginWeightList.get(i));
mCurrentWeightList.set(i, weight);
}
if (isRepeatable)
mCurrentWeightList.set(nextPos, calculateWeight(0, mOriginWeightList.get(nextPos)));
else
mCurrentWeightList.set(nextPos, 0);
if (isCutMode()) {
mCurrentWeightList.set(nextPos, 0);
mCutOutSet.add(nextPos);
if (mCutOutSet.size() >= getSize())
mCutOutSet.clear();
}
return nextPos;
}
p.s. 如果你有更好的建议,请留言或者在GitHub fork并提交pull请求。