- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在研究音乐播放器,它可以在 fragment 上显示来自本地设备的所有歌曲和相应歌曲的图像。
当我启动该应用程序时,它需要很长时间才能加载,我注意到是 getImagesForSongs() 处理缓慢
为什么这么慢?有没有更好的方法,我该怎么做?
My All Song fragment 类
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.mikeinvents.musicbaze.R;
import com.mikeinvents.musicbaze.adapters.SongAdapter;
import com.mikeinvents.musicbaze.data_model.SongModel;
import com.mikeinvents.musicbaze.ui.MainActivity;
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* A simple {@link Fragment} subclass.
*/
public class AllSongsFragment extends Fragment {
RecyclerView recyclerView;
ArrayList<SongModel> song;
ArrayList<Bitmap> bitmaps;
MediaMetadataRetriever mediaMetadataRetriever;
static byte[] rawArt;
static Bitmap art;
static BitmapFactory.Options bfo;
public AllSongsFragment() {
// Required empty public constructor
}
@Override
public void onStart() {
super.onStart();
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_all_songs, container, false);
// setRetainInstance(true);
recyclerView = rootView.findViewById(R.id.song_recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
new MyAsyncTask().execute();
return rootView;
}
private void loadSongList() {
ContentResolver contentResolver = Objects.requireNonNull(getActivity()).getContentResolver();
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selection = MediaStore.Audio.Media.IS_MUSIC;
String sortOrder = MediaStore.Audio.Media.TITLE + " ASC";
Cursor cursor = contentResolver.query(uri,null,selection,null,sortOrder);
if(cursor != null && cursor.moveToFirst()){
song = new ArrayList<>();
//get columns
do {
String data = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
String title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
String album = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM));
String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
String timeDuration = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION));
//convert time
int duration = Integer.parseInt(timeDuration);
@SuppressLint("DefaultLocale") String time = String.format("%02d:%02d",
TimeUnit.MILLISECONDS.toMinutes(duration),
TimeUnit.MILLISECONDS.toSeconds(duration) -
TimeUnit.MILLISECONDS
.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration)));
//save to list
song.add(new SongModel(data, title, artist, album, time));
Log.i(MainActivity.TAG, " Added: "+"data = "+data+" title = "+title+
" album = "+album+" artist: "+artist+" duration = "+time);
}while (cursor.moveToNext());
}
if(cursor !=null){
cursor.close();
}
}
private void getImagesForSongs(){
ContentResolver contentResolver = Objects.requireNonNull(getActivity()).getContentResolver();
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selection = MediaStore.Audio.Media.IS_MUSIC;
String sortOrder = MediaStore.Audio.Media.TITLE + " ASC";
Cursor cursor = contentResolver.query(uri,null,selection,null,sortOrder);
if(cursor != null && cursor.moveToFirst()){
bitmaps = new ArrayList<>();
do{
String data = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
//get song image
mediaMetadataRetriever = new MediaMetadataRetriever();
mediaMetadataRetriever.setDataSource(data);
Log.i(MainActivity.TAG, "Data source has been set");
rawArt = mediaMetadataRetriever.getEmbeddedPicture();
Log.i(MainActivity.TAG, "Raw art has been gotten");
bfo = new BitmapFactory.Options();
art = decodeSampledBitmapFromResource(100,100);
//save to list
bitmaps.add(art);
}while (cursor.moveToNext());
}
if (cursor != null) {
cursor.close();
}
}
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 4;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
Log.i(MainActivity.TAG,"Calculated in sample size");
return inSampleSize;
}
public static Bitmap decodeSampledBitmapFromResource(int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
bfo.inJustDecodeBounds = true;
if(rawArt != null){
BitmapFactory.decodeByteArray(rawArt,0,rawArt.length,bfo);
Log.i(MainActivity.TAG, "Gotten embedded picture");
// Calculate inSampleSize
calculateInSampleSize(bfo,reqWidth,reqHeight);
// Decode bitmap with inSampleSize set
bfo.inJustDecodeBounds = false;
return BitmapFactory.decodeByteArray(rawArt,0,rawArt.length,bfo);
}
Log.i(MainActivity.TAG, "Gotten null embedded picture");
return null;
}
private class MyAsyncTask extends AsyncTask<Void, Void, Void>{
ProgressDialog pd;
@Override
protected void onPreExecute() {
super.onPreExecute();
pd = new ProgressDialog(getContext());
pd.setTitle("Please wait...");
pd.setMessage("Fetching songs");
pd.setCancelable(false);
pd.show();
}
@Override
protected Void doInBackground(Void... voids) {
getImagesForSongs();
loadSongList();
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
pd.dismiss();
SongAdapter songAdapter = new SongAdapter(getContext(), song, bitmaps);
Log.i(MainActivity.TAG,"Initialized adapter");
recyclerView.setAdapter(songAdapter);
Log.i(MainActivity.TAG,"Adapter has been set");
}
}
}
我的 SongAdapter 类
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.TextView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.mikeinvents.musicbaze.R;
import com.mikeinvents.musicbaze.data_model.SongModel;
import com.mikeinvents.musicbaze.ui.MainActivity;
import java.util.ArrayList;
public class SongAdapter extends RecyclerView.Adapter<SongAdapter.ViewHolder> {
private Context ctx;
private ArrayList<SongModel> mSong;
private ArrayList<Bitmap> mBitmap;
public SongAdapter(Context ct, ArrayList<SongModel> song, ArrayList<Bitmap> bitmap){
ctx = ct;
mSong = song;
mBitmap = bitmap;
}
@NonNull
@Override
public SongAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
LayoutInflater inflater = LayoutInflater.from(ctx);
View view = inflater.inflate(R.layout.song_row,viewGroup,false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull SongAdapter.ViewHolder viewHolder, int i) {
SongModel song = mSong.get(i);
viewHolder.songTitle.setText(song.getTitle());
viewHolder.songArtist.setText(song.getArtist());
viewHolder.songAlbum.setText(song.getAlbum());
viewHolder.songTime.setText(song.getSongTime());
// Glide.with(ctx).load(mBitmap.get(i)).fallback(R.drawable.mojo_logo).into(viewHolder.songImage);
if(mBitmap.get(i) == null){
viewHolder.songImage.setImageResource(R.drawable.mojo_logo);
}else if(mBitmap.get(i) !=null){
viewHolder.songImage.setImageBitmap(mBitmap.get(i));
}
viewHolder.moreOptions.setOnClickListener(v -> {
PopupMenu popupMenu = new PopupMenu(ctx,v);
popupMenu.setOnMenuItemClickListener(item -> {
switch (item.getItemId()){
case R.id.more_options_action_share:
Toast.makeText(ctx,"Implement Share Option", Toast.LENGTH_SHORT).show();
return true;
case R.id.more_options_action_add_fav:
Toast.makeText(ctx,"Implement Favorite Option", Toast.LENGTH_SHORT).show();
return true;
case R.id.more_options_action_delete:
Toast.makeText(ctx,"Implement Delete Option", Toast.LENGTH_SHORT).show();
return true;
default:
return false;
}
});
popupMenu.inflate(R.menu.more_options_popup);
popupMenu.show();
});
}
@Override
public int getItemCount() {
return mSong.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView songImage, moreOptions;
TextView songTitle, songArtist, songAlbum, songTime;
public ViewHolder(@NonNull View itemView) {
super(itemView);
songImage = itemView.findViewById(R.id.song_row_song_image);
moreOptions = itemView.findViewById(R.id.song_row_more_options);
songTitle = itemView.findViewById(R.id.song_row_name_of_song);
songArtist = itemView.findViewById(R.id.song_row_artist_name);
songAlbum = itemView.findViewById(R.id.song_row_album_name);
songTime = itemView.findViewById(R.id.song_row_song_time);
Log.i(MainActivity.TAG,"Views in song_row layout initialized");
}
}
}
谢谢。
最佳答案
不确定是否有具体的修复,但可以做一些事情来加快加载速度。
位图可能会很慢,所以如果可以获得 png 图像而不是这将加快该过程。在 decodeSampledBitmapFromResource 方法中,运行
BitmapFactory.decodeByteArray(rawArt,0,rawArt.length,bfo);
两次,这似乎无关紧要,但也许我错过了什么。
此外,您可以延迟加载图像而不是一次加载每首歌曲的所有图像,您可以在 onBindViewHolder 中获取图像。这样,每个图像也将以并行方式异步获取。
关于java - 歌曲图像可以更快吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58557807/
我正在从事从媒体选择器中挑选歌曲并将数据发送到服务器的项目。我正在转换选择的歌曲。它适用于普通歌曲(即不属于购买的 iTunes 的歌曲),对于购买的歌曲,我收到错误消息。我集成了由苹果提供的这个示例
一旦进入包含.mp3 文件的目录,我就可以随机播放歌曲了 mpg123 -Z *.mp3 但是如果我想递归搜索目录及其子文件夹中的 .mp3 文件并随机播放它们,我尝试了以下命令,但它不起作用。 mp
我有 2 种不同的方法来使用内容解析器检索歌曲。一个用于获取手机上的所有歌曲,一个用于从手机中检索所有播放列表,然后,对于每个播放列表,我获取其中的歌曲并将其添加到播放列表对象。为此,我在所有歌曲列表
我正在从 SD 卡中获取我的歌曲并将其放入 ListView 。 我正在使用这个方法。但它需要一些时间,如果路径不同,我没有得到该数据。 所以,QUE 是否有任何有用的脚本可以显示我所有 SD 卡中的
我正在使用 MPMusicPlayerController.systemMusicPlayer 的一个实例来对商店 ID 数组进行排队。这已经工作了几个月了。今天早些时候我更新到 iOS 14.3,现
如果我使用mp3: "/Music/StreamUploadedSongs/1"在以下代码中: var player = new $("#jquery_jplayer_1").jPlayer({
我正在开发一个 iOS 应用程序,我需要允许用户将 iTunes 中的几首歌曲的预览播放到应用程序中。现在,通过查找 API 和 adamID,我可以轻松找到预览 URL 并让它播放。 我rad
我们可以使用 NAudio 播放 mp4 歌曲吗?请提供一些播放mp4歌曲的代码我需要一个 c# 代码来帮助我播放 mp4 歌曲 最佳答案 可以用NAudio播放.mp4文件,官网有demo。 下载演
我想获取歌曲在特定时间段内的收听次数。使用 MPMediaItemPropertyLastPlayedDate 我只能获取上次播放歌曲的日期,因此如果我每天多次播放歌曲,则只有最后一次才算数。基本上,
我们可以使用 NAudio 播放 mp4 歌曲吗?请提供一些播放mp4歌曲的代码我需要一个 c# 代码来帮助我播放 mp4 歌曲 最佳答案 可以用NAudio播放.mp4文件,官网有demo。 下载演
我正在制作一个闹钟。我有下面的代码。但是,通知音乐正在发挥作用。我想让它播放我设置的mp3文件。我该怎么办? @Override public void onReceive(Context c
我想在我的 Java 游戏中播放 .wav 格式的歌曲,下面是 SoundPlayer 类的一些代码: private static HashMap clips; private static int
我有一个可以播放本地歌曲的 Android 服务(我遵循了这个教程:https://code.tutsplus.com/tutorials/create-a-music-player-on-andro
这个问题在这里已经有了答案: HTML 5 video or audio playlist (12 个答案) 关闭 6 年前。 我想让我的网站播放多首 mp3/歌曲,但它一直在播放 soundtra
我正在从 android 中的 sdcard 访问歌曲,歌曲显示在 ListView 中,但我无法播放这些文件。 代码如下: package com.ex.imageGallery; import a
我正在尝试创建一个嵌入了一些 JavaScript 的 HTML 文件,该文件允许我按下按钮并开始淡出歌曲。我已经设法让它工作,以便它播放歌曲(这是一个开始)。但我一直在尝试使用第二个功能来尝试降低音
将 iTunes 中最后播放的歌曲的信息获取到 Java 程序中的最简单方法是什么?我看过 JACOB 和 iTunes COM,但它们似乎有点过分了。如果这是唯一的方法,有人可以在第一个谷歌结果旁边
我想从 python 播放我的歌曲 (mp3),你能给我一个最简单的命令吗? 这是不正确的: import wave w = wave.open("e:/LOCAL/Betrayer/Metalik
我有一个歌曲列表 - 有没有办法(使用 Spotify/Echo Nest API)批量查找每个轨道的 Spotify ID? 如果有帮助,我计划通过其 API 的“获取音频功能”部分运行这些 ID。
我正在为一个乐队制作一个 iPhone 应用程序,其中列出了该乐队的歌曲。当用户触摸歌曲旁边的按钮时,我想打开 iTunes 并显示该歌曲。目前我正在使用这段代码: [[UIApplication共享
我是一名优秀的程序员,十分优秀!