无法从Activity调用RecyclerView Adapter方法,需后台执行数据库操作
解决AsyncTask调用Adapter方法找不到&后台数据库操作卡顿问题
我来帮你搞定这两个问题:首先是Android Studio提示找不到setdataEntries方法的报错,然后是优化后台数据库操作避免界面卡顿(顺便说下,AsyncTask已经被官方废弃了,我会给你推荐更现代的替代方案)。
一、解决“找不到setdataEntries方法”的核心问题
你在Activity里把Adapter声明成了RecyclerView.Adapter类型,而setdataEntries是你自定义的EntryAdapter里的方法,父类RecyclerView.Adapter并没有这个方法,所以编译器识别不到。
修复步骤:
把Activity里的Adapter变量声明从:
private RecyclerView.Adapter adapater;
改成:
private EntryAdapter adapater;
这样初始化的时候:
adapater = new EntryAdapter(this); recyclerView.setAdapter(adapater);
之后在FetchDataTask的onPostExecute里调用adapater.setdataEntries(Data)就不会报错了。
二、优化后台数据库操作(替代废弃的AsyncTask)
AsyncTask在API 30已经被官方标记为废弃,而且容易引发内存泄漏,推荐使用协程来执行后台操作,这也是Room官方推荐的方式,能更安全地处理后台任务和UI更新。
1. 先把Room数据库改成单例模式(避免重复创建实例)
每次创建新的Room数据库实例会浪费资源,建议把AppDatabase改成单例:
public abstract class AppDatabase extends RoomDatabase { public abstract EntryDao entryDao(); // 单例实例 private static volatile AppDatabase INSTANCE; public static AppDatabase getInstance(Context context) { if (INSTANCE == null) { synchronized (AppDatabase.class) { if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "production") .build(); } } } return INSTANCE; } }
2. 用协程替换AsyncTask
删除原来的FetchDataTask内部类,修改dataView方法:
public void dataView() { String site= extras.getString("sitename"); recyclerView.setVisibility(View.VISIBLE); mLoadingIndicator.setVisibility(View.VISIBLE); // 使用Activity的lifecycleScope,自动跟随生命周期销毁,避免内存泄漏 lifecycleScope.launch(Dispatchers.IO) { try { // 获取单例数据库实例 AppDatabase db = AppDatabase.getInstance(getApplicationContext()); List<UserTuple> entries = db.entryDao().getSpecific(site); // 解密数据 for(UserTuple ut : entries){ Log.i("password",ut.getPassword()); String st = new Decryption().decrypt(ut.getPassword(),key()); Log.i("After decryption",st); ut.setPassword(st); } // 切回主线程更新UI withContext(Dispatchers.Main) { mLoadingIndicator.setVisibility(View.INVISIBLE); adapater.setdataEntries(entries); } } catch (Exception e) { e.printStackTrace(); // 切回主线程处理错误 withContext(Dispatchers.Main) { mLoadingIndicator.setVisibility(View.INVISIBLE); showerror(); } } } }
这样既避免了主线程卡顿,又解决了AsyncTask的潜在问题。
三、额外的小修复
你在onCreate里有一行代码会导致空指针:
Log.i("Logins","Size of returned list "+entries.size());
这里entries还没初始化,直接调用size()会崩溃,建议删掉这行,或者移到数据加载完成后再打印。
内容的提问来源于stack exchange,提问作者Abhimanyu Ravilla
相关产品推荐
相关产品推荐

