Prevent concurrent queue modifications from breaking the cast demo app UI

PiperOrigin-RevId: 233577854
This commit is contained in:
aquilescanta 2019-02-12 11:30:54 +00:00 committed by Andrew Lewis
parent 3a5ed6b889
commit 55e6d1d708
2 changed files with 34 additions and 15 deletions

View File

@ -211,6 +211,7 @@ public class MainActivity extends AppCompatActivity
private class QueueItemViewHolder extends RecyclerView.ViewHolder implements OnClickListener {
public final TextView textView;
public MediaItem item;
public QueueItemViewHolder(TextView textView) {
super(textView);
@ -236,8 +237,9 @@ public class MainActivity extends AppCompatActivity
@Override
public void onBindViewHolder(QueueItemViewHolder holder, int position) {
holder.item = playerManager.getItem(position);
TextView view = holder.textView;
view.setText(playerManager.getItem(position).title);
view.setText(holder.item.title);
// TODO: Solve coloring using the theme's ColorStateList.
view.setTextColor(ColorUtils.setAlphaComponent(view.getCurrentTextColor(),
position == playerManager.getCurrentItemIndex() ? 255 : 100));
@ -278,7 +280,8 @@ public class MainActivity extends AppCompatActivity
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int position = viewHolder.getAdapterPosition();
if (playerManager.removeItem(position)) {
QueueItemViewHolder queueItemHolder = (QueueItemViewHolder) viewHolder;
if (playerManager.removeItem(queueItemHolder.item)) {
mediaQueueListAdapter.notifyItemRemoved(position);
// Update whichever item took its place, in case it became the new selected item.
mediaQueueListAdapter.notifyItemChanged(position);
@ -289,8 +292,9 @@ public class MainActivity extends AppCompatActivity
public void clearView(RecyclerView recyclerView, ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
if (draggingFromPosition != C.INDEX_UNSET) {
QueueItemViewHolder queueItemHolder = (QueueItemViewHolder) viewHolder;
// A drag has ended. We reflect the media queue change in the player.
if (!playerManager.moveItem(draggingFromPosition, draggingToPosition)) {
if (!playerManager.moveItem(queueItemHolder.item, draggingToPosition)) {
// The move failed. The entire sequence of onMove calls since the drag started needs to be
// invalidated.
mediaQueueListAdapter.notifyDataSetChanged();

View File

@ -168,10 +168,16 @@ import java.util.ArrayList;
/**
* Removes the item at the given index from the media queue.
*
* @param itemIndex The index of the item to remove.
* @param item The item to remove.
* @return Whether the removal was successful.
*/
public boolean removeItem(int itemIndex) {
public boolean removeItem(MediaItem item) {
int itemIndex = mediaQueue.indexOf(item);
if (itemIndex == -1) {
// This may happen if another sender app removes items while this sender app is in "swiping
// an item" state.
return false;
}
concatenatingMediaSource.removeMediaSource(itemIndex);
mediaQueue.remove(itemIndex);
if (currentPlayer == exoCastPlayer) {
@ -188,20 +194,29 @@ import java.util.ArrayList;
/**
* Moves an item within the queue.
*
* @param fromIndex The index of the item to move.
* @param toIndex The target index of the item in the queue.
* @return Whether the item move was successful.
* @param item The item to move. This method does nothing if {@code item} is not contained in the
* queue.
* @param toIndex The target index of the item in the queue. If {@code toIndex} exceeds the last
* position in the queue, {@code toIndex} is clamped to match the largest possible value.
* @return True if {@code item} was contained in the queue, and {@code toIndex} was a valid
* position. False otherwise.
*/
public boolean moveItem(int fromIndex, int toIndex) {
mediaQueue.add(toIndex, mediaQueue.remove(fromIndex));
concatenatingMediaSource.moveMediaSource(fromIndex, toIndex);
if (currentPlayer == exoCastPlayer) {
exoCastPlayer.moveItemInQueue(fromIndex, toIndex);
public boolean moveItem(MediaItem item, int toIndex) {
int indexOfItem = mediaQueue.indexOf(item);
if (indexOfItem == -1) {
// This may happen if another sender app removes items while this sender app is in "dragging
// an item" state.
return false;
}
int clampedToIndex = Math.min(toIndex, mediaQueue.size() - 1);
mediaQueue.add(clampedToIndex, mediaQueue.remove(indexOfItem));
concatenatingMediaSource.moveMediaSource(indexOfItem, clampedToIndex);
if (currentPlayer == exoCastPlayer) {
exoCastPlayer.moveItemInQueue(indexOfItem, clampedToIndex);
}
// Index update.
maybeSetCurrentItemAndNotify(currentPlayer.getCurrentWindowIndex());
return true;
return clampedToIndex == toIndex;
}
// Miscellaneous methods.