安卓音乐应用切换标签崩溃:SQLite无_display_name列异常求助
解决安卓音乐应用切换标签崩溃的SQLiteException问题
咱们先直接看抛出的错误日志:
android.database.sqlite.SQLiteException: no such column: _display_name (code 1): , while compiling: SELECT name, 0, _display_name FROM audio_genres
这个错误其实非常直白——你在查询安卓媒体库的**流派表(audio_genres)**时,请求了一个根本不存在的字段_display_name,导致SQLite编译查询语句失败,最终触发应用崩溃。
问题根源拆解
- 字段误用:你代码里的
dName=MediaStore.Audio.Media.DISPLAY_NAME是属于**音频文件(单首歌曲)**的字段,而流派表(MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI对应的表)里没有这个列,强行查询必然报错。 - 实例化方法错误:你的
newInstance方法返回的是BlankFragment,但当前类是BlankFragment3,这会导致Fragment实例化异常(虽然这次崩溃不是直接因为这个,但也是潜在问题)。 - ID字段处理冗余:你把
MediaStore.Audio.Genres._ID转成Long再转回String,完全没必要,直接用常量字段名即可。
分步解决方案
1. 移除无效字段,修正查询逻辑
把查询列里的MediaStore.Audio.Media.DISPLAY_NAME删掉,只保留流派表存在的字段(ID和名称)。如果需要展示流派下的歌曲信息,要通过流派ID关联查询音频文件表,而不是硬塞不存在的字段。
2. 修正Fragment实例化方法
确保newInstance返回的是当前类BlankFragment3的实例,避免实例化错误。
3. 同步调整数据类和适配器
因为移除了dName字段,需要同步修改genreInfo数据类和genreAdapter的代码,避免空指针或无效引用。
修正后的关键代码
修正BlankFragment3的核心方法
// 修正newInstance方法,返回正确的Fragment实例 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; } // 修正getGenreList方法,只查询流派表存在的字段 public void getGenreList(){ final Uri uri = MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI; String genreId = MediaStore.Audio.Genres._ID; String genreName = MediaStore.Audio.Genres.NAME; // 仅查询流派ID和名称两个有效字段 final String[] columns = { genreId, genreName }; Cursor cursor = getContext().getContentResolver().query(uri, columns, null, null, null); if(cursor!=null && cursor.moveToFirst()) { do { long id = cursor.getLong(cursor.getColumnIndex(genreId)); String name = cursor.getString(cursor.getColumnIndex(genreName)); // 调整构造方法,去掉无效的dName参数 genreInfo g = new genreInfo(id, name); genreList.add(g); } while (cursor.moveToNext()); cursor.close(); } // 用notifyDataSetChanged更新数据,比重新设置适配器更高效 genreAdapter1.notifyDataSetChanged(); }
修正genreInfo数据类
public class genreInfo { private long id; private String name; // 去掉dName参数,保留流派核心信息 public genreInfo(long id, String name) { this.id = id; this.name = name; } // 保留必要的getter方法 public long getId() { return id; } public String getName() { return name; } }
修正genreAdapter的绑定逻辑
@Override public void onBindViewHolder(AlbumHolder holder, int position) { final genreInfo a = genreList.get(position); holder.album.setText(a.getName()); // 如果需要展示额外信息(比如流派歌曲数量),可以在这里添加查询逻辑 // 示例:holder.artist.setText(getSongCountForGenre(a.getId()) + "首歌"); }
额外优化:展示流派歌曲数量
如果想给每个流派加上歌曲数量,可以添加一个辅助方法:
private int getSongCountForGenre(long genreId) { Cursor cursor = getContext().getContentResolver().query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, new String[]{"COUNT(*)"}, MediaStore.Audio.Media.GENRE_ID + " = ?", new String[]{String.valueOf(genreId)}, null ); int count = 0; if(cursor != null && cursor.moveToFirst()) { count = cursor.getInt(0); cursor.close(); } return count; }
内容的提问来源于stack exchange,提问作者devesh kumawat
相关产品推荐
相关产品推荐

