我有一个JobIntentService,它可以从SQLite数据库重新设置挂起的警报通知.它使用一个查询和一个游标从数据库中的4个不同列获取通知日期。我正在转换到一个Room数据库,并且不确定如何将光标转换为Dao方法。我是否需要使用@Transaction,因为我从数据库中的多个列获得通知?会很感激你对如何在房间里建房的任何见解或想法。
Service
public class Service extends JobIntentService {
static final int JOB_ID = 9;
public static void enqueueWork(Context context, Intent work) {
enqueueWork(context, RebootService.class, JOB_ID, work);
}
@Override
protected void onHandleWork(@NonNull Intent intent) {
AlarmManager alarmManager1;
Intent brIntent1;
PendingIntent pendingIntent1;
SQLiteDB sqLiteDB = SQLiteDB.getInstance(this);
Calendar cal1 = Calendar.getInstance();
Cursor cursor = sqLiteDB.resetNotifications();
try {
if (cursor.getCount() > 0) {
cursor.moveToFirst();
int dueDatentimeColumnIndex = cursor.getColumnIndex(ItemContract.ItemEntry.COLUMN_DUEDATENTIME);
int notifColumnIndex1 = cursor.getColumnIndex(ItemContract.ItemEntry.COLUMN_NOTIFTIME);
int notif2ColumnIndex2 = cursor.getColumnIndex(ItemContract.ItemEntry.COLUMN_NOTIFTIME2);
int randColumnIndex1 = cursor.getColumnIndex(ItemContract.ItemEntry.COLUMN_RANDINT);
while (!cursor.isAfterLast()) {
do {
long notifTime1 = cursor.getLong(notifColumnIndex1);
int randInt1 = cursor.getInt(randColumnIndex1);
cal1.setTime(new Date(notifTime1));
// Set up a system AlarmManager to fire a future alarm that sends a Notification
// even if the app is in the background or closed.
alarmManager1 = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
if (cal1.getTimeInMillis() > System.currentTimeMillis()) {
brIntent1 = new Intent(this, AlarmReceiver.class);
brIntent1.setAction("24Hour");
pendingIntent1 = PendingIntent.getBroadcast(this, randInt1, brIntent1,
PendingIntent.FLAG_ONE_SHOT);
if (alarmManager1 != null && notifTime1 != -1) {
alarmManager1.set(AlarmManager.RTC_WAKEUP, cal1.getTimeInMillis(), pendingIntent1);
}
...
}
SQLiteDB.java
...
public Cursor resetNotifications() {
SQLiteDatabase db = getReadableDatabase();
String[] columns = new String[]{
ItemContract.ItemEntry.COLUMN_NOTIFTIME,
ItemContract.ItemEntry.COLUMN_NOTIFTIME2,
ItemContract.ItemEntry.COLUMN_DUEDATENTIME,
ItemContract.ItemEntry.COLUMN_RANDINT};
return db.query(
TABLE_NAME,
columns, // The columns to return
null,
null,
null,
null,
null
);
}
This is the code I came up as a replacement:
public class RebootService extends JobIntentService {
// Unique job ID for this service
static final int JOB_ID = 10000;
// Convenience method for enqueueing work to this service.
public static void enqueueWork(Context context, Intent work) {
enqueueWork(context, RebootService.class, JOB_ID, work);
}
private QuickcardRepository reposit1;
@Override
protected void onHandleWork(@NonNull Intent intent) {
reposit1 = new QuickcardRepository(getApplication());
Bundle extras = intent.getExtras(); // Returns the Intent *that started this Service.*
if (extras != null) {
String classname = extras.getString("TAG");
if (classname != null && classname.equals("bootCompleted")) {
AlarmManager alarmManager1;
Intent brIntent1, brIntent2, brIntent3;
PendingIntent pendingIntent1, pendingIntent2, pendingIntent3;
Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
Calendar cal3 = Calendar.getInstance();
List<Quickcard> resetNotificationsList = reposit1.getNotifications();
// Cycle through the Room database rows to get the Notifications data
for (Quickcard quickcard: resetNotificationsList) {
// Quickcards without a Due date get a Due date in the database of -1.
// Therefore, only cycle through and get data for those quickcards that have
// a Due data and therefore have Notifications (reminders) where the actual
// "Due date" is != -1.
if(quickcard.getDuedatentime() != -1) {
// Set up the 24-Hour calendar object.
long notifTime1 = quickcard.getNotiftime();
int randInt1 = quickcard.getRandint();
cal1.setTime(new Date(notifTime1));
// Set up a system AlarmManager to fire a future alarm that sends a Notification
// even if the app is in the background or closed. Have to add "context" here.
alarmManager1 = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
// If the stated alarm trigger time is in the past, the alarm will be triggered immediately.
// So only set Alarms to fire Notifications for Duedates in the future
// (meaning > than the current System time). Ignore those in the past.
if (cal1.getTimeInMillis() > System.currentTimeMillis()) {
// For the 24Hour Notifications.
// Set up a PendingIntent that will perform broadcast to the BroadcastReceiver.
brIntent1 = new Intent(this, AlarmReceiver.class);
brIntent1.setAction("24Hour");
// Need to use FLAG_ONE_SHOT on the PendingIntent, not FLAG_UPDATE_CURRENT.
// A random int is used to be able to set multiple alarms and then to be able to
// delete them later (if the user for ex., deletes the quickCards Duedate) using
// the same random int.
pendingIntent1 = PendingIntent.getBroadcast(this, randInt1, brIntent1,
PendingIntent.FLAG_ONE_SHOT);
// Alarms have 3 properties below after "set(...)":
// 1) Alarm type: RTC_WAKEUP type is chosen here to wake the device from sleep.
// 2) Trigger time: in this case, 24 hours before the Duedate/Duetime is reached.
// 3) Pending Intent: A future Intent that is sent when the trigger time is reached.
int SDK_INT1 = Build.VERSION.SDK_INT;
if (SDK_INT1 >= Build.VERSION_CODES.M) {
// Wakes up the device in Doze Mode for API Level 23 and higher.
// The "... != -1" test only sets up pendingIntents for quickCards that have
// a Notification. quickCards with no Duedate & Duetime are bypassed.
if (alarmManager1 != null && notifTime1 != -1) {
alarmManager1.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal1.getTimeInMillis(),
pendingIntent1);
}
} else if (SDK_INT1 >= Build.VERSION_CODES.KITKAT) {
// Wakes up the device in Idle Mode for API Level 19 to 22.
// The "... != -1" test only sets up pendingIntents for quickCards that have
// a Notification. quickCards with no Duedate & Duetime are bypassed.
if (alarmManager1 != null && notifTime1 != -1) {
alarmManager1.setExact(AlarmManager.RTC_WAKEUP, cal1.getTimeInMillis(), pendingIntent1);
}
} else {
// Old APIs Level 18 and below.
// The "... != -1" test only sets up pendingIntents for quickCards that have
// a Notification. quickCards with no Duedate & Duetime are bypassed.
if (alarmManager1 != null && notifTime1 != -1) {
alarmManager1.set(AlarmManager.RTC_WAKEUP, cal1.getTimeInMillis(), pendingIntent1);
}
}
}发布于 2019-05-28 03:40:59
我相信@ transaction 将代码包装在事务中。除了 @Query 之外,其他所有查询都已完成(如果@查询不是更新/删除查询(如果是更新或删除查询,则将其包装在事务中)。
我认为,是否应该在事务(@Transaction @Query......)中包装SELECT查询的问题是是否使用@Relation。如果是,则相关/关联项/对象的列表作为单独的查询运行,因此在事务中运行它们将确保数据的一致性。如果没有潜在的潜在性,基础数据可能会被其他事务更改,因此由此产生的数据可能是不一致的。
他说,在不需要@Transaction的地方使用它几乎不会产生影响,如果它是在无意中没有被编码的地方编码,甚至可能会产生积极的影响。
当然,无论如何,您都可以使用Room返回游标。您可能想看看Associating tables using Room database in Android Studio,它有一些示例。
基于您的代码,主要是您有一个带有ItemEntry.java,子类ItemEntry的ItemContract,那么ItemEntry的实体可以在ItemEntry中,如下所示:-
@Entity
public class ItemEntry {
@PrimaryKey(autoGenerate = true)
private long id;
@ColumnInfo(name = COLUMN_NOTIFTIME)
private long notiftime;
@ColumnInfo(name = COLUMN_NOTIFTIME2)
private long notiftime2;
@ColumnInfo(name = COLUMN_DUEDATENTIME)
private long duedatentime;
@ColumnInfo(name = COLUMN_RANDINT)
public int randint;
public ItemEntry(){
}
@Ignore
public ItemEntry(long notiftime, long notiftime2, long duedatentime, int randint) {
this.notiftime = notiftime;
this.notiftime2 = notiftime2;
this.duedatentime = duedatentime;
this.randint = randint;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public long getNotiftime() {
return notiftime;
}
public void setNotiftime(long notiftime) {
this.notiftime = notiftime;
}
public long getNotiftime2() {
return notiftime2;
}
public void setNotiftime2(long notiftime2) {
this.notiftime2 = notiftime2;
}
public long getDuedatentime() {
return duedatentime;
}
public void setDuedatentime(long duedatentime) {
this.duedatentime = duedatentime;
}
public int getRandint() {
return randint;
}
public void setRandint(int randint) {
this.randint = randint;
}
} 与接口ItemEntryDao.java一起作为:-
@Dao
interface ItemEntryDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
long[] insertItemEntries(ItemEntry... itemEntries);
@Insert(onConflict = OnConflictStrategy.IGNORE)
long insertItemEntry(ItemEntry itemEntry);
@Update(onConflict = OnConflictStrategy.IGNORE)
int updateItemEnrties(ItemEntry... itemEntries);
@Update(onConflict = OnConflictStrategy.IGNORE)
int updateItemEntry(ItemEntry itemEntry);
@Delete
int deleteItemEntries(ItemEntry... itemEntries);
@Delete
int deleteItemEntry(ItemEntry itemEntry);
@Query("SELECT * FROM ItemEntry")
List<ItemEntry> resetNotifications();
}例如,上面的内容(基本上是复制您的代码,但将提取的数据输出到日志中)如下:
public void onHandleWork() {
ItemEntry ie = new ItemEntry();
ie.setNotiftime(100);
ie.setNotiftime2(200);
ie.setDuedatentime(500000);
ie.setRandint(567);
mDB.getItemEntryDao().insertItemEntry(ie);
List<ItemEntry> mylist = mDB.getItemEntryDao().resetNotifications();
for (ItemEntry itementry: mylist) {
Log.d("ITEMENTRY",
"\n\tnotiftime= " + String.valueOf(itementry.getNotiftime()) +
"\n\tnotiftime2= " + String.valueOf(itementry.getNotiftime2()) +
"\n\tduedatetime= " + String.valueOf(itementry.getDuedatentime()) +
"\n\trandint= " + String.valueOf(itementry.getRandint())
);
}
}这将导致(第一轮) :-
05-28 14:31:14.587 7211-7211/aso.so56326640D/ITEMENTRY: notiftime= 100 notiftime2= 200 duedatetime= 500000 randint= 567
https://stackoverflow.com/questions/56328482
复制相似问题