使用Room在Android BroadcastReceiver中访问数据库

5
我设置了一个每小时调用广播接收器的闹钟。该接收器尝试从SQLite数据库中加载数据。
问题在于,提醒列表为空。相同代码在活动中有效,但在接收器中无效。我是否需要更改以在接收器中访问数据库?这是否与活动和接收器中不同的上下文有关?
“setAlarm”方法是我在活动中创建闹钟的方法。
问候。
public class AppReceiver extends BroadcastReceiver {

    private static final String TAG = "AppReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        ReminderRepository mRepository; = new ReminderRepository(context);
        List<Reminder> list = mRepository.getAllReminder();
        for(Reminder r : list) {
            // TODO
        }
    }
}


public class ReminderRepository {

    private ReminderDao mReminderDao;
    private List<Reminder> mAllReminder;

    public DisposalCalenderRepository(Context context) {
        ReminderRoomDatabase db = ReminderRoomDatabase.getDatabase(context);
        mReminderDao = db.reminderDao();
        mAllReminder = mReminderDao.getAll();
    }

    public List<Reminder> getAllReminder(){
        return mAllReminder;
    }

}

@Dao
public interface ReminderDao {

    @Query("SELECT * from reminder")
    List<Reminder> getAll();

}

public void setAlarm(){
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.add(Calendar.HOUR, 1);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);

    AlarmManager alarmMgr = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
    Intent i = new Intent(mContext, AppReceiver.class);
    PendingIntent alarmIntent = PendingIntent.getBroadcast(mContext, 0, i, 0);

    alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
                AlarmManager.INTERVAL_HOUR, alarmIntent);
    }

你在Logcat中的错误是什么?还是只返回了0个项目?处理来自唤醒的广播在时间上有一些限制,可能也涉及到互联网使用,但除非你能提供更多信息,否则不确定。 - Sam
日志中没有出现错误。我只收到了一个空指针异常,因为“list”变量为空。所以NPE出现在for循环中。 - Ephenodrom
嗯,从技术上讲,Room会阻止某些线程的访问,但这应该会显示为错误。因此,您可以尝试使用async{}调用来获取它并返回值。可能不会解决问题,但值得一试。另外,它是否进入DAO进行调用,您能够调试多远,然后失去了对发生情况的视野并需要添加日志记录? - Sam
当我直接调用DAO时,会出现错误,提示无法在主线程上访问数据库。 - Ephenodrom
1个回答

7

我发现了两个可能的答案来回答我的问题。

解决方案1:启动异步任务。创建一个AsyncTask类并在doBackground方法中执行相关操作。这样就不会再有访问数据库的问题了。

@Override
public void onReceive(Context context, Intent intent) {
    new notifyAsyncTask().execute(context);
}

private static class notifyAsyncTask extends AsyncTask<Context, Void, Void> {

        private String CHANNEL_ID = "1a2b3c4d";

        private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        @Override
        protected Void doInBackground(Context... params) {
            Log.i(TAG, "Notify async started");
        ReminderRepository mRepository; = new ReminderRepository(context);
        List<Reminder> list = mRepository.getAllReminder();
        for(Reminder r : list) {
                // TODO
        }
    }
}

解决方案2:允许在主线程上查询。在构建数据库时,使用allowMainThreadQueries()允许在主线程上进行查询。 !!!! 注意 !!!! 不推荐使用 !!!! 注意 !!!!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接