RecyclerView Adapter点击崩溃:非Activity上下文启动需FLAG_ACTIVITY_NEW_TASK
先看你给出的崩溃日志,核心问题非常明确:
android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
这是因为你在Adapter里用了ApplicationContext启动Intent,而ApplicationContext并非Activity上下文,默认不允许直接启动新的Activity任务。另外你还需要把占位的Google链接替换为JSON里的真实link字段,同时还要修正MainActivity里的一个JSON解析小问题,下面一步步来解决:
1. 修正上下文传递问题
在MainActivity初始化Adapter的时候,别再传getApplicationContext()了,直接传当前Activity的上下文this就行:
// 原来的代码 adapter = new Adapter(getApplicationContext(),songs); // 修改后 adapter = new Adapter(MainActivity.this, songs);
这样Adapter里的context就是Activity上下文,启动Intent时就不会触发这个崩溃了。
2. 替换占位链接为JSON中的真实链接
在Adapter的ViewHolder点击事件里,获取当前列表项对应的Song对象的link字段,替换掉占位的Google链接:
artTitle.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 获取当前item对应的链接 String targetUrl = songs.get(getAdapterPosition()).getLink(); Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(targetUrl)); context.startActivity(intent); } });
这里用getAdapterPosition()获取当前ViewHolder的位置比直接用position更可靠,毕竟列表数据更新时,position可能会出现偏差。
3. 修复MainActivity里的JSON解析小错误
你的MainActivity里有一行冗余代码,多了不必要的.toString():
// 原来的代码 song.setJournal(songObject.getString("journal".toString())); // 修改后 song.setJournal(songObject.getString("journal"));
虽然这行代码不会直接导致崩溃,但属于冗余写法,容易引发误解,建议修正。
额外优化小建议
- 可以给整个CardView添加点击事件,让用户点击卡片任意位置都能跳转,体验更好:
在ViewHolder的构造函数里,给itemView设置点击事件:itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String targetUrl = songs.get(getAdapterPosition()).getLink(); Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(targetUrl)); context.startActivity(intent); } }); - 可以给链接加个空值判断,避免JSON里的
link为空导致的崩溃:String targetUrl = songs.get(getAdapterPosition()).getLink(); if (targetUrl != null && !targetUrl.isEmpty()) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(targetUrl)); context.startActivity(intent); } else { Toast.makeText(context, "链接无效", Toast.LENGTH_SHORT).show(); }
把这些修改完成后,你的应用应该就能正常跳转,不会再崩溃了。
内容的提问来源于stack exchange,提问作者new2linux

