mirror of
https://github.com/antebudimir/tempus.git
synced 2026-04-16 00:37:25 +00:00
fix: Prevent externalAudioReader from hogging the main thread
This commit is contained in:
parent
1357c5c062
commit
620fba0a14
12 changed files with 242 additions and 90 deletions
|
|
@ -11,6 +11,7 @@ import android.widget.Filterable;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.session.MediaBrowser;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
|
@ -25,6 +26,7 @@ import com.cappielloantonio.tempo.subsonic.models.DiscTitle;
|
|||
import com.cappielloantonio.tempo.util.Constants;
|
||||
import com.cappielloantonio.tempo.util.DownloadUtil;
|
||||
import com.cappielloantonio.tempo.util.ExternalAudioReader;
|
||||
import com.cappielloantonio.tempo.util.MappingUtil;
|
||||
import com.cappielloantonio.tempo.util.MusicUtil;
|
||||
import com.cappielloantonio.tempo.util.Preferences;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
|
@ -90,7 +92,7 @@ public class SongHorizontalAdapter extends RecyclerView.Adapter<SongHorizontalAd
|
|||
}
|
||||
};
|
||||
|
||||
public SongHorizontalAdapter(ClickCallback click, boolean showCoverArt, boolean showAlbum, AlbumID3 album) {
|
||||
public SongHorizontalAdapter(LifecycleOwner lifecycleOwner, ClickCallback click, boolean showCoverArt, boolean showAlbum, AlbumID3 album) {
|
||||
this.click = click;
|
||||
this.showCoverArt = showCoverArt;
|
||||
this.showAlbum = showAlbum;
|
||||
|
|
@ -99,6 +101,10 @@ public class SongHorizontalAdapter extends RecyclerView.Adapter<SongHorizontalAd
|
|||
this.currentFilter = "";
|
||||
this.album = album;
|
||||
setHasStableIds(false);
|
||||
|
||||
if (lifecycleOwner != null) {
|
||||
MappingUtil.observeExternalAudioRefresh(lifecycleOwner, this::handleExternalAudioRefresh);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
@ -204,6 +210,12 @@ public class SongHorizontalAdapter extends RecyclerView.Adapter<SongHorizontalAd
|
|||
bindPlaybackState(holder, song);
|
||||
}
|
||||
|
||||
private void handleExternalAudioRefresh() {
|
||||
if (Preferences.getDownloadDirectoryUri() != null) {
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void bindPlaybackState(@NonNull ViewHolder holder, @NonNull Child song) {
|
||||
boolean isCurrent = currentPlayingId != null && currentPlayingId.equals(song.getId());
|
||||
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ public class AlbumPageFragment extends Fragment implements ClickCallback {
|
|||
bind.songRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
bind.songRecyclerView.setHasFixedSize(true);
|
||||
|
||||
songHorizontalAdapter = new SongHorizontalAdapter(this, false, false, album);
|
||||
songHorizontalAdapter = new SongHorizontalAdapter(getViewLifecycleOwner(), this, false, false, album);
|
||||
bind.songRecyclerView.setAdapter(songHorizontalAdapter);
|
||||
setMediaBrowserListenableFuture();
|
||||
reapplyPlayback();
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ public class ArtistPageFragment extends Fragment implements ClickCallback {
|
|||
private void initTopSongsView() {
|
||||
bind.mostStreamedSongRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
|
||||
songHorizontalAdapter = new SongHorizontalAdapter(this, true, true, null);
|
||||
songHorizontalAdapter = new SongHorizontalAdapter(getViewLifecycleOwner(), this, true, true, null);
|
||||
bind.mostStreamedSongRecyclerView.setAdapter(songHorizontalAdapter);
|
||||
setMediaBrowserListenableFuture();
|
||||
reapplyPlayback();
|
||||
|
|
|
|||
|
|
@ -600,7 +600,7 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback {
|
|||
|
||||
bind.topSongsRecyclerView.setHasFixedSize(true);
|
||||
|
||||
topSongAdapter = new SongHorizontalAdapter(this, true, false, null);
|
||||
topSongAdapter = new SongHorizontalAdapter(getViewLifecycleOwner(), this, true, false, null);
|
||||
bind.topSongsRecyclerView.setAdapter(topSongAdapter);
|
||||
setTopSongsMediaBrowserListenableFuture();
|
||||
reapplyTopSongsPlayback();
|
||||
|
|
@ -641,7 +641,7 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback {
|
|||
|
||||
bind.starredTracksRecyclerView.setHasFixedSize(true);
|
||||
|
||||
starredSongAdapter = new SongHorizontalAdapter(this, true, false, null);
|
||||
starredSongAdapter = new SongHorizontalAdapter(getViewLifecycleOwner(), this, true, false, null);
|
||||
bind.starredTracksRecyclerView.setAdapter(starredSongAdapter);
|
||||
setStarredSongsMediaBrowserListenableFuture();
|
||||
reapplyStarredSongsPlayback();
|
||||
|
|
|
|||
|
|
@ -264,7 +264,7 @@ public class PlaylistPageFragment extends Fragment implements ClickCallback {
|
|||
bind.songRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
bind.songRecyclerView.setHasFixedSize(true);
|
||||
|
||||
songHorizontalAdapter = new SongHorizontalAdapter(this, true, false, null);
|
||||
songHorizontalAdapter = new SongHorizontalAdapter(getViewLifecycleOwner(), this, true, false, null);
|
||||
bind.songRecyclerView.setAdapter(songHorizontalAdapter);
|
||||
setMediaBrowserListenableFuture();
|
||||
reapplyPlayback();
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ public class SearchFragment extends Fragment implements ClickCallback {
|
|||
bind.searchResultTracksRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
bind.searchResultTracksRecyclerView.setHasFixedSize(true);
|
||||
|
||||
songHorizontalAdapter = new SongHorizontalAdapter(this, true, false, null);
|
||||
songHorizontalAdapter = new SongHorizontalAdapter(getViewLifecycleOwner(), this, true, false, null);
|
||||
setMediaBrowserListenableFuture();
|
||||
reapplyPlayback();
|
||||
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ public class SongListPageFragment extends Fragment implements ClickCallback {
|
|||
bind.songListRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
bind.songListRecyclerView.setHasFixedSize(true);
|
||||
|
||||
songHorizontalAdapter = new SongHorizontalAdapter(this, true, false, null);
|
||||
songHorizontalAdapter = new SongHorizontalAdapter(getViewLifecycleOwner(), this, true, false, null);
|
||||
bind.songListRecyclerView.setAdapter(songHorizontalAdapter);
|
||||
setMediaBrowserListenableFuture();
|
||||
reapplyPlayback();
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import android.widget.TextView;
|
|||
import android.widget.Toast;
|
||||
import android.widget.ToggleButton;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.media3.common.MediaItem;
|
||||
|
|
@ -56,6 +57,10 @@ public class AlbumBottomSheetDialog extends BottomSheetDialogFragment implements
|
|||
private AlbumBottomSheetViewModel albumBottomSheetViewModel;
|
||||
private AlbumID3 album;
|
||||
|
||||
private TextView removeAllTextView;
|
||||
private List<Child> currentAlbumTracks = Collections.emptyList();
|
||||
private List<MediaItem> currentAlbumMediaItems = Collections.emptyList();
|
||||
|
||||
private ListenableFuture<MediaBrowser> mediaBrowserListenableFuture;
|
||||
|
||||
@Nullable
|
||||
|
|
@ -74,6 +79,12 @@ public class AlbumBottomSheetDialog extends BottomSheetDialogFragment implements
|
|||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
MappingUtil.observeExternalAudioRefresh(getViewLifecycleOwner(), this::updateRemoveAllVisibility);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
|
@ -188,23 +199,23 @@ public class AlbumBottomSheetDialog extends BottomSheetDialogFragment implements
|
|||
});
|
||||
});
|
||||
|
||||
TextView removeAll = view.findViewById(R.id.remove_all_text_view);
|
||||
removeAllTextView = view.findViewById(R.id.remove_all_text_view);
|
||||
albumBottomSheetViewModel.getAlbumTracks().observe(getViewLifecycleOwner(), songs -> {
|
||||
List<MediaItem> mediaItems = MappingUtil.mapDownloads(songs);
|
||||
List<Download> downloads = songs.stream().map(Download::new).collect(Collectors.toList());
|
||||
currentAlbumTracks = songs != null ? songs : Collections.emptyList();
|
||||
currentAlbumMediaItems = MappingUtil.mapDownloads(currentAlbumTracks);
|
||||
|
||||
removeAll.setOnClickListener(v -> {
|
||||
removeAllTextView.setOnClickListener(v -> {
|
||||
if (Preferences.getDownloadDirectoryUri() == null) {
|
||||
DownloadUtil.getDownloadTracker(requireContext()).remove(mediaItems, downloads);
|
||||
List<Download> downloads = currentAlbumTracks.stream().map(Download::new).collect(Collectors.toList());
|
||||
DownloadUtil.getDownloadTracker(requireContext()).remove(currentAlbumMediaItems, downloads);
|
||||
} else {
|
||||
songs.forEach(ExternalAudioReader::delete);
|
||||
currentAlbumTracks.forEach(ExternalAudioReader::delete);
|
||||
}
|
||||
dismissBottomSheet();
|
||||
});
|
||||
updateRemoveAllVisibility();
|
||||
});
|
||||
|
||||
initDownloadUI(removeAll);
|
||||
|
||||
TextView goToArtist = view.findViewById(R.id.go_to_artist_text_view);
|
||||
goToArtist.setOnClickListener(v -> albumBottomSheetViewModel.getArtist().observe(getViewLifecycleOwner(), artist -> {
|
||||
if (artist != null) {
|
||||
|
|
@ -244,21 +255,29 @@ public class AlbumBottomSheetDialog extends BottomSheetDialogFragment implements
|
|||
dismiss();
|
||||
}
|
||||
|
||||
private void initDownloadUI(TextView removeAll) {
|
||||
albumBottomSheetViewModel.getAlbumTracks().observe(getViewLifecycleOwner(), songs -> {
|
||||
List<MediaItem> mediaItems = MappingUtil.mapDownloads(songs);
|
||||
private void updateRemoveAllVisibility() {
|
||||
if (removeAllTextView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Preferences.getDownloadDirectoryUri() == null) {
|
||||
if (DownloadUtil.getDownloadTracker(requireContext()).areDownloaded(mediaItems)) {
|
||||
removeAll.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
removeAll.setVisibility(View.GONE);
|
||||
}
|
||||
if (currentAlbumTracks == null || currentAlbumTracks.isEmpty()) {
|
||||
removeAllTextView.setVisibility(View.GONE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Preferences.getDownloadDirectoryUri() == null) {
|
||||
List<MediaItem> mediaItems = currentAlbumMediaItems;
|
||||
if (mediaItems == null || mediaItems.isEmpty()) {
|
||||
removeAllTextView.setVisibility(View.GONE);
|
||||
} else if (DownloadUtil.getDownloadTracker(requireContext()).areDownloaded(mediaItems)) {
|
||||
removeAllTextView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
boolean hasLocal = songs.stream().anyMatch(song -> ExternalAudioReader.getUri(song) != null);
|
||||
removeAll.setVisibility(hasLocal ? View.VISIBLE : View.GONE);
|
||||
removeAllTextView.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
boolean hasLocal = currentAlbumTracks.stream().anyMatch(song -> ExternalAudioReader.getUri(song) != null);
|
||||
removeAllTextView.setVisibility(hasLocal ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeMediaBrowser() {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import android.widget.TextView;
|
|||
import android.widget.Toast;
|
||||
import android.widget.ToggleButton;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
|
|
@ -53,6 +54,9 @@ public class SongBottomSheetDialog extends BottomSheetDialogFragment implements
|
|||
private SongBottomSheetViewModel songBottomSheetViewModel;
|
||||
private Child song;
|
||||
|
||||
private TextView downloadButton;
|
||||
private TextView removeButton;
|
||||
|
||||
private ListenableFuture<MediaBrowser> mediaBrowserListenableFuture;
|
||||
|
||||
@Nullable
|
||||
|
|
@ -71,6 +75,12 @@ public class SongBottomSheetDialog extends BottomSheetDialogFragment implements
|
|||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
MappingUtil.observeExternalAudioRefresh(getViewLifecycleOwner(), this::updateDownloadButtons);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
|
@ -162,8 +172,8 @@ public class SongBottomSheetDialog extends BottomSheetDialogFragment implements
|
|||
dismissBottomSheet();
|
||||
});
|
||||
|
||||
TextView download = view.findViewById(R.id.download_text_view);
|
||||
download.setOnClickListener(v -> {
|
||||
downloadButton = view.findViewById(R.id.download_text_view);
|
||||
downloadButton.setOnClickListener(v -> {
|
||||
if (Preferences.getDownloadDirectoryUri() == null) {
|
||||
DownloadUtil.getDownloadTracker(requireContext()).download(
|
||||
MappingUtil.mapDownload(song),
|
||||
|
|
@ -175,8 +185,8 @@ public class SongBottomSheetDialog extends BottomSheetDialogFragment implements
|
|||
dismissBottomSheet();
|
||||
});
|
||||
|
||||
TextView remove = view.findViewById(R.id.remove_text_view);
|
||||
remove.setOnClickListener(v -> {
|
||||
removeButton = view.findViewById(R.id.remove_text_view);
|
||||
removeButton.setOnClickListener(v -> {
|
||||
if (Preferences.getDownloadDirectoryUri() == null) {
|
||||
DownloadUtil.getDownloadTracker(requireContext()).remove(
|
||||
MappingUtil.mapDownload(song),
|
||||
|
|
@ -188,7 +198,7 @@ public class SongBottomSheetDialog extends BottomSheetDialogFragment implements
|
|||
dismissBottomSheet();
|
||||
});
|
||||
|
||||
initDownloadUI(download, remove);
|
||||
updateDownloadButtons();
|
||||
|
||||
TextView addToPlaylist = view.findViewById(R.id.add_to_playlist_text_view);
|
||||
addToPlaylist.setOnClickListener(v -> {
|
||||
|
|
@ -256,21 +266,19 @@ public class SongBottomSheetDialog extends BottomSheetDialogFragment implements
|
|||
dismiss();
|
||||
}
|
||||
|
||||
private void initDownloadUI(TextView download, TextView remove) {
|
||||
private void updateDownloadButtons() {
|
||||
if (downloadButton == null || removeButton == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Preferences.getDownloadDirectoryUri() == null) {
|
||||
if (DownloadUtil.getDownloadTracker(requireContext()).isDownloaded(song.getId())) {
|
||||
remove.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
download.setVisibility(View.VISIBLE);
|
||||
remove.setVisibility(View.GONE);
|
||||
}
|
||||
boolean downloaded = DownloadUtil.getDownloadTracker(requireContext()).isDownloaded(song.getId());
|
||||
downloadButton.setVisibility(downloaded ? View.GONE : View.VISIBLE);
|
||||
removeButton.setVisibility(downloaded ? View.VISIBLE : View.GONE);
|
||||
} else {
|
||||
if (ExternalAudioReader.getUri(song) != null) {
|
||||
remove.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
download.setVisibility(View.VISIBLE);
|
||||
remove.setVisibility(View.GONE);
|
||||
}
|
||||
boolean hasLocal = ExternalAudioReader.getUri(song) != null;
|
||||
downloadButton.setVisibility(hasLocal ? View.GONE : View.VISIBLE);
|
||||
removeButton.setVisibility(hasLocal ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue