RecyclerView报错No adapter attached; skipping layout,列表不显示求助
解决RecyclerView报错:
E/RecyclerView: No adapter attached; skipping layout 及列表空白问题 我仔细排查了你的代码,找到了几个核心问题,这就是导致你遇到RecyclerView报错、列表空白的关键原因:
1. 最致命的错误:onCreateView返回了null
你的onCreateView方法最后一行写的是return null;,但实际上你已经通过inflater.inflate创建了Fragment的布局View对象v。返回null会直接导致整个Fragment的布局都不会被渲染,RecyclerView自然无法显示出来。
2. 加载歌曲后未正确更新RecyclerView数据
在loadSongs方法里,你重新创建了一个songAdapter1实例,但没有把这个新Adapter绑定到RecyclerView上;而且就算你只是往原有的_songs集合里添加数据,也需要通知Adapter数据更新,否则RecyclerView不会刷新显示新内容。
3. MediaPlayer未初始化存在空指针风险
在Item点击事件中,你直接调用mediaPlayer.isPlaying(),但第一次点击时mediaPlayer还是null状态,会触发空指针异常,导致点击逻辑执行失败。
修正后的完整代码
public class SongsTab extends Fragment { private ArrayList<songInfo> _songs = new ArrayList<>(); RecyclerView recyclerView; SeekBar seekBar; songAdapter songAdapter1; MediaPlayer mediaPlayer; private Handler myHandler = new Handler(); Cursor cursor; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.songs, container, false); recyclerView = v.findViewById(R.id.recyclerView); seekBar = v.findViewById(R.id.seekBar); // 初始化Adapter并绑定到RecyclerView songAdapter1 = new songAdapter(_songs, getContext()); LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity()); DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), linearLayoutManager.getOrientation()); recyclerView.setLayoutManager(linearLayoutManager); recyclerView.addItemDecoration(dividerItemDecoration); recyclerView.setAdapter(songAdapter1); songAdapter1.setOnitemClickListener(new songAdapter.OnitemClickListener() { @Override public void onItemclick(songAdapter.ViewHolder holder, View v, songInfo obj, int position) { System.gc(); int songPathIndex = cursor.getColumnIndex(MediaStore.Audio.Media.DATA); cursor.moveToPosition(position); final String filename = cursor.getString(songPathIndex); // 先判断mediaPlayer是否为null,避免空指针 if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.stop(); mediaPlayer.reset(); mediaPlayer.release(); mediaPlayer = null; } else { Runnable runnable = new Runnable() { @Override public void run() { try { mediaPlayer = new MediaPlayer(); mediaPlayer.setDataSource(filename); mediaPlayer.prepareAsync(); mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.start(); seekBar.setProgress(0); seekBar.setMax(mediaPlayer.getDuration()); Log.d("Prog", "run: " + mediaPlayer.getDuration()); } }); } catch (Exception e) { e.printStackTrace(); // 不要吞掉异常,方便后续排查问题 } } }; myHandler.postDelayed(runnable, 100); } } }); checkUserPermission(); Thread t = new runThread(); t.start(); // 返回正确的View对象,而不是null return v; } public class runThread extends Thread { @Override public void run() { while (true) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } Log.d("Runwa", "run: " + 1); // 增加播放状态判断,避免不必要的UI更新 if (mediaPlayer != null && mediaPlayer.isPlaying()) { seekBar.post(new Runnable() { @Override public void run() { seekBar.setProgress(mediaPlayer.getCurrentPosition()); } }); Log.d("Runwa", "run: " + mediaPlayer.getCurrentPosition()); } } } } private void checkUserPermission(){ if(Build.VERSION.SDK_INT>=23){ if(ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){ requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},123); return; } } loadSongs(); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode){ case 123: if (grantResults[0] == PackageManager.PERMISSION_GRANTED){ loadSongs(); }else{ Toast.makeText(getContext(), "Permission Denied", Toast.LENGTH_SHORT).show(); checkUserPermission(); } break; default: super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } private void loadSongs(){ Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; String selection = MediaStore.Audio.Media.IS_MUSIC+"!=0"; cursor =getActivity().getContentResolver().query(uri,null,selection,null,null); if(cursor != null){ _songs.clear(); // 先清空旧数据,避免重复加载 if(cursor.moveToFirst()){ do{ String name = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)); String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)); // 修正:存储实际文件路径,而不是列索引 String songPath = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA)); songInfo s = new songInfo(name,artist,songPath); _songs.add(s); }while (cursor.moveToNext()); } cursor.close(); // 不需要重新创建Adapter,直接通知数据更新即可 songAdapter1.notifyDataSetChanged(); } } }
额外说明
- 我还修正了
loadSongs里的一个逻辑错误:你之前把MediaStore.Audio.Media.DATA的列索引存到了songInfo里,这显然不对,应该存储实际的文件路径字符串。 - 建议不要吞掉异常(比如之前的
catch (Exception e) { }),打印异常信息能帮你快速排查后续可能遇到的问题。
内容的提问来源于stack exchange,提问作者devesh kumawat
相关产品推荐
相关产品推荐

