Android中MyAdapter的onRequestPermissionsResult报错:未覆写父类方法
问题原因分析
你遇到的does not override or implement a method from a supertype错误,核心原因很简单:onRequestPermissionsResult是Activity或Fragment类的专属方法,而你的MyAdapter继承的是BaseAdapter——BaseAdapter根本没有这个方法,所以你用@Override注解去重写它,编译器自然会报错。之前在其他项目里能正常使用,是因为你当时把这个方法写在了Activity类里,而不是Adapter里。
解决方案:把权限回调逻辑移到Activity中
Adapter的职责是负责列表项的渲染和交互触发,权限请求这类和组件生命周期相关的操作,应该交给Activity来处理。我们可以通过接口回调的方式,让Adapter和Activity配合完成权限请求和下载逻辑,具体步骤如下:
1. 在MyAdapter中定义回调接口
用来通知Activity发起权限请求,以及在权限通过后触发下载操作:
public class MyAdapter extends BaseAdapter { // 新增回调接口 public interface PermissionDownloadCallback { // 请求存储权限,同时传递当前要下载的参数 void requestStoragePermission(String fileName, String dirPath, String audioUrl); // 权限通过后执行下载 void onPermissionGranted(String fileName, String dirPath, String audioUrl); } private static final int PERMISSION_REQUEST_CODE = 1; String fileName; String dirPath; Context context; ArrayList<StoryModel> TitleAndImage ; ArrayList<StoryModel> forShowEachStoryInNewActivity ; LayoutInflater inflter; // 新增回调实例 private PermissionDownloadCallback callback; // 修改构造方法,传入回调 public MyAdapter(Context context, ArrayList<StoryModel> TitleAndImage, ArrayList<StoryModel> forShowEachStoryInNewActivity, PermissionDownloadCallback callback) { this.context = context; this.TitleAndImage = TitleAndImage; this.forShowEachStoryInNewActivity=forShowEachStoryInNewActivity; this.callback = callback; inflter = LayoutInflater.from(context); } // ... 原有的getCount、getItem等方法保持不变 ... // 修改下载按钮的点击逻辑 b1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dirPath = com.example.abdullah.newstroynory.Utils.getRootDirPath(context); String title_For_Download = forShowEachStoryInNewActivity.get(position).getTitle(); fileName = title_For_Download + ".mp3"; String audio_For_Download = forShowEachStoryInNewActivity.get(position).getAudio(); if (Build.VERSION.SDK_INT >= 23) { if (checkPermission()) { // 权限已通过,直接触发下载 dorDownloadMyAudios(fileName, dirPath, audio_For_Download); } else { // 通知Activity发起权限请求,并传递下载参数 callback.requestStoragePermission(fileName, dirPath, audio_For_Download); } } else { // 低于23的系统无需权限,直接下载 dorDownloadMyAudios(fileName, dirPath, audio_For_Download); } } }); // ... 原有的checkPermission方法保持不变 ... // 删除原来的onRequestPermissionsResult方法,因为Adapter里不能重写它 // 把下载方法改成public,让Activity可以调用 public void dorDownloadMyAudios(String fileName, String dirPath, String url){ PRDownloader.initialize(context); PRDownloaderConfig config = PRDownloaderConfig.newBuilder() .setDatabaseEnabled(true) .build(); PRDownloader.initialize(context, config); int downloadId = PRDownloader.download(url, dirPath, fileName) .build() .setOnStartOrResumeListener(new OnStartOrResumeListener() { @Override public void onStartOrResume() { } }) .setOnPauseListener(new OnPauseListener() { @Override public void onPause() { } }) .setOnProgressListener(new OnProgressListener() { @Override public void onProgress(Progress progress) { } }) .start(new OnDownloadListener() { @Override public void onDownloadComplete() { Toast.makeText(context, "下载完成!", Toast.LENGTH_SHORT).show(); } @Override public void onError(Error error) { Toast.makeText(context, "下载失败:" + error.getMessage(), Toast.LENGTH_SHORT).show(); } }); } }
2. 在对应的Activity中实现回调接口
把权限请求和回调逻辑放在Activity里处理:
public class YourStoryActivity extends AppCompatActivity implements MyAdapter.PermissionDownloadCallback { private MyAdapter adapter; // 暂存要下载的参数,权限通过后使用 private String pendingFileName; private String pendingDirPath; private String pendingAudioUrl; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.your_activity_layout); // 初始化列表数据(这里替换成你自己的数据源) ArrayList<StoryModel> titleAndImageList = new ArrayList<>(); ArrayList<StoryModel> storyList = new ArrayList<>(); // 创建Adapter时传入当前Activity作为回调 adapter = new MyAdapter(this, titleAndImageList, storyList, this); ListView listView = findViewById(R.id.list_view); listView.setAdapter(adapter); } @Override public void requestStoragePermission(String fileName, String dirPath, String audioUrl) { // 暂存下载参数 this.pendingFileName = fileName; this.pendingDirPath = dirPath; this.pendingAudioUrl = audioUrl; // 发起权限请求 if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { Toast.makeText(this, "存储权限允许我们保存文件,请在设置中开启该权限", Toast.LENGTH_LONG).show(); } else { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MyAdapter.PERMISSION_REQUEST_CODE); } } @Override public void onPermissionGranted(String fileName, String dirPath, String audioUrl) { // 权限通过,触发下载 adapter.dorDownloadMyAudios(fileName, dirPath, audioUrl); } // 重写Activity的权限回调方法 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == MyAdapter.PERMISSION_REQUEST_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Log.e("权限状态", "权限已授予,可以使用本地存储"); // 通知Adapter执行下载 onPermissionGranted(pendingFileName, pendingDirPath, pendingAudioUrl); // 清空暂存参数 pendingFileName = null; pendingDirPath = null; pendingAudioUrl = null; } else { Log.e("权限状态", "权限被拒绝,无法下载文件"); Toast.makeText(this, "权限被拒绝,无法完成下载", Toast.LENGTH_SHORT).show(); } } } }
这样修改后,权限请求和回调逻辑就完全交给Activity处理,Adapter只负责触发交互和执行下载,既符合Android的设计规范,也能解决你遇到的编译错误。
内容的提问来源于stack exchange,提问作者Abdullah Khudher
相关产品推荐
相关产品推荐

