Android获取MediaStore音乐流派列表失败,界面空白无报错求解决
我帮你排查了代码里的几个关键问题,这应该就是界面空白的原因,咱们一步步来修复:
1. Cursor遍历跳过了首项数据
在getGenreList方法里,你先调用cursor.moveToFirst(),紧接着又调用cursor.moveToNext(),这会直接跳过第一个流派的数据——如果你的设备里只有一个流派,就会完全加载不到内容。
修改主Cursor的遍历逻辑,改成直接用while循环(会自动处理空Cursor的情况):
public void getGenreList() { String[] proj1 = new String[]{ MediaStore.Audio.Genres.NAME, MediaStore.Audio.Genres._ID }; ContentResolver cr = getContext().getContentResolver(); cursor = cr.query(MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI, proj1, null, null, null); // 修正后的遍历逻辑 if (cursor != null) { while (cursor.moveToNext()) { int index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Genres.NAME); String genre = cursor.getString(index); index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Genres._ID); long genreId = Long.parseLong(cursor.getString(index)); Uri uri = MediaStore.Audio.Genres.Members.getContentUri("external", genreId); Cursor tempCursor = cr.query(uri, null, null, null, null); // 子Cursor同样修正遍历逻辑 if (tempCursor != null) { while (tempCursor.moveToNext()) { index = tempCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE); String title = tempCursor.getString(index); index = tempCursor.getColumnIndexOrThrow(MediaStore.Audio.Artists.ARTIST); String artist = tempCursor.getString(index); index = tempCursor.getColumnIndexOrThrow(MediaStore.Audio.Albums.ALBUM); String album = tempCursor.getString(index); genreInfo g = new genreInfo(artist, title, album, genre); genreList.add(g); } tempCursor.close(); } } cursor.close(); // 别忘了关闭Cursor,避免内存泄漏 // 关键:通知Adapter数据更新 genreAdapter1.notifyDataSetChanged(); } }
2. 未通知RecyclerView数据更新
你加载完所有数据后,没有调用genreAdapter1.notifyDataSetChanged(),RecyclerView不知道数据已经更新,所以即使数据加载成功,界面也不会刷新。上面的代码已经把这行加上了,放在Cursor关闭之后。
3. Fragment实例化方法错误
你的newInstance方法返回的是BlankFragment,但你的类名是BlankFragment3,这会导致实例化错误(如果这个方法被调用的话),赶紧修正:
public static BlankFragment3 newInstance(String param1, String param2) { BlankFragment3 fragment = new BlankFragment3(); Bundle args = new Bundle(); args.putString(ARG_PARAM1, param1); args.putString(ARG_PARAM2, param2); fragment.setArguments(args); return fragment; }
4. 确认需求匹配:流派列表VS流派下的歌曲
注意:你当前的代码逻辑是把每个流派下的所有歌曲都添加到列表中,相当于显示所有歌曲并附带流派标签;但如果你的需求是显示流派列表(每个项是一个流派名称,比如“摇滚”“流行”),那你的逻辑就错了,应该改成每个流派只添加一次,示例如下:
// 修改后的getGenreList,用于获取流派列表(每个流派一条数据) public void getGenreList() { String[] proj1 = new String[]{ MediaStore.Audio.Genres.NAME, MediaStore.Audio.Genres._ID }; ContentResolver cr = getContext().getContentResolver(); cursor = cr.query(MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI, proj1, null, null, null); if (cursor != null) { while (cursor.moveToNext()) { int index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Genres.NAME); String genreName = cursor.getString(index); long genreId = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Genres._ID)); // 获取该流派下的歌曲数量 Uri membersUri = MediaStore.Audio.Genres.Members.getContentUri("external", genreId); Cursor countCursor = cr.query(membersUri, new String[]{"COUNT(*)"}, null, null, null); int songCount = 0; if (countCursor != null && countCursor.moveToFirst()) { songCount = countCursor.getInt(0); countCursor.close(); } // 添加流派信息到列表(需要修改genreInfo的构造方法,支持传入流派名称和歌曲数量) genreList.add(new genreInfo(genreName, songCount)); } cursor.close(); genreAdapter1.notifyDataSetChanged(); } }
同时要对应修改genreAdapter的布局和绑定逻辑,显示流派名称和歌曲数量,而不是歌曲的标题、艺术家等信息。
5. 权限检查(补充)
虽然你说歌曲和专辑能正常获取,但还是确认一下:Android 6.0+需要动态请求READ_EXTERNAL_STORAGE权限,在Fragment的onViewCreated里添加权限检查:
@Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // 检查存储权限 if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(requireActivity(), new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1001); } else { // 权限已授予,加载数据 getGenreList(); } } // 处理权限请求结果 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 1001 && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { getGenreList(); } }
按照上面的步骤修改后,应该就能正常显示内容了,如果还有问题,可以告诉我你的具体需求(是显示流派列表还是流派下的歌曲)以及测试设备的Android版本,我再帮你进一步排查。
内容的提问来源于stack exchange,提问作者devesh kumawat

