等待Preferences Datastore从workmanager中的首选项数据存储检索数据



我的应用程序正在后台检查未读电子邮件,问题是我需要在上次检查电子邮件时保存和检索lastCheckedDate,这样我只能显示新收到的电子邮件。

为了从数据存储中检索数据,我使用observeLastCheckedDate((,并且我必须用handler调用它,因为如果我不这样做,我会得到:

java.lang.IollegalStateException:无法在后台线程上调用observe

函数observeLastCheckedDate((被调用,但当它完成(更新lastCheckedDate(时,workManager任务已经完成,但没有更新var lastCheckedDate。

在main类中,我通过创建和调用回调来避免这个问题,但在这里它不起作用(它会使整个应用程序冻结(,所以我们需要等待该函数完成,或者从数据存储中获得一些新的检索数据的方法。

class WorkerMan(private val mContext: Context, workerParameters: WorkerParameters) :
CoroutineWorker(mContext, workerParameters) {
private lateinit var settingsManager: SettingsManager
var lastCheckedDate: Long = 0
@SuppressLint("RestrictedApi", "CheckResult")
val email = inputData.getString("email")
val password = inputData.getString("password")
val token = inputData.getString("token")
fun saveLastCheckedDate(lastCheckedDate: Long) {
GlobalScope.launch {
settingsManager.storeLastCheckedDate(lastCheckedDate)
}
}
private fun observeLastCheckedDate() {
settingsManager.lastCheckedDateFlow.asLiveData().observe(
ProcessLifecycleOwner.get(),
{
lastCheckedDate = it
println("LASTCHECKEDDATE LOADED")
}
)
}

@SuppressLint("RestrictedApi", "WrongThread")
override suspend fun doWork(): Result {
withContext(Dispatchers.IO) {
settingsManager = SettingsManager(getApplicationContext())

var messageCounter = 0;

val handler = Handler(Looper.getMainLooper())
handler.post {
observeLastCheckedDate()
}

println("**************************************************************************")
println("**************************************************************************")
println("WorkManager: Work called")
println("WorkManager email: " + email)
println("WorkManager: Last Checked Moment : " + lastCheckedDate.toString())
println("WorkManager:      Current Moment : " + Instant.now().toEpochMilli())
println("**************************************************************************")
println("**************************************************************************")
try {
val session = Session.getDefaultInstance(Properties())
val store = session.getStore("imaps")
store.connect(
"mail.metropolitan.ac.rs",
993,
email,
password
)
val inbox = store.getFolder("INBOX")
inbox.open(Folder.READ_ONLY)

val messages = inbox.search(
FlagTerm(Flags(Flags.Flag.SEEN), false)
)
Arrays.sort(
messages
) { m1: Message, m2: Message ->
try {
return@sort m2.sentDate.compareTo(m1.sentDate)
} catch (e: MessagingException) {
throw RuntimeException(e)
}
}

//            println("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ")
//            println("WorkManager Started")
//            println("WorkMananager email: " + email)
//            val current = LocalTime.now()
//            println("WorkMananager time: " + current)
//            println("Messages amount: " + messages.size)
//            println("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ")
for (message in messages) {
Thread.sleep(1000)
messageCounter++
if (message.receivedDate.toInstant().toEpochMilli() >= lastCheckedDate) {
Thread.sleep(1000)
println("=====================================================")
println("NOTIFIKACIJA")
var title = ""
for (element in message.from) {
title += element.toString().substringAfter("<").substringBefore(">")
title += " "
}
println("Title :" + title)
println("Subject :" + message.subject)
println("Datum i vreme : " + message.receivedDate)
title.replace("[", "")
title.replace("]", "")
send(token, message.subject, title)
}
if (messageCounter > 10) {
break
}
}
saveLastCheckedDate(Instant.now().toEpochMilli())
println("=====================================================")
Log.d("WorkManager", "Job finished")
} catch (e: Exception) {
Log.d("WorkManager error", "doWork not executed")
Log.d("WorkManager error", "error: ")
Log.d("WorkManager error", e.printStackTrace().toString())
} catch (e: NetworkOnMainThreadException) {
Log.d("WorkManager error", "doWork not executed")
Log.d("WorkManager error", "NetworkOnMainThreadException: ")
Log.d("WorkManager error", e.toString())
}
}
return Result.Success();
}
}
fun send(to: String?, body: String?, title: String?): String? {
try {
val apiKey =
"***************************************"
val url = URL("https://fcm.googleapis.com/fcm/send")
val conn = url.openConnection() as HttpURLConnection
conn.doOutput = true
conn.requestMethod = "POST"
conn.setRequestProperty("Content-Type", "application/json")
conn.setRequestProperty("Authorization", "key=$apiKey")
conn.doOutput = true
val message = JSONObject()
message.put("to", to)
message.put("priority", "high")
val notification = JSONObject()
notification.put("title", title)
notification.put("body", body)
message.put("notification", notification)
val os = conn.outputStream
os.write(message.toString().toByteArray())
os.flush()
os.close()
val responseCode = conn.responseCode
println("nSending 'POST' request to URL : $url")
println("Post parameters : $message")
println("Response Code : $responseCode")
println("Response Code : " + conn.responseMessage)
val `in` = BufferedReader(InputStreamReader(conn.inputStream))
var inputLine: String?
val response = StringBuffer()
while (`in`.readLine().also { inputLine = it } != null) {
response.append(inputLine)
}
`in`.close()
println(response.toString())
return response.toString()
} catch (e: Exception) {
Log.d("WorkManager error", "send not executed")
Log.d("WorkManager error", "error: ")
Log.d("WorkManager error", e.printStackTrace().toString())
} catch (e: NetworkOnMainThreadException) {
Log.d("WorkManager error", "send() not executed")
Log.d("WorkManager error", "NetworkOnMainThreadException: ")
Log.d("WorkManager error", e.toString())
}
return "error"
}

数据存储类:

class SettingsManager(context: Context) {
private val dataStore = context.createDataStore(name = "user_settings_preferencess")

companion object {
val ENABLE_NOTIFICATIONS = preferencesKey<Int>("ENABLE_NOTIFICATIONS")
val ENABLE_MAIL_NOTIFICATIONS = preferencesKey<Int>("ENABLE_MAIL_NOTIFICATIONS")
val LAST_CHECKED_DATE = preferencesKey<Long>("LAST_CHECKED_DATE")
}

//Store user data
suspend fun storeNotifications(enableNotifications: Int) {
dataStore.edit {
it[ENABLE_NOTIFICATIONS] = enableNotifications

}
}
suspend fun storeMailNotifications(enableMailNotifications: Int) {
dataStore.edit {
it[ENABLE_MAIL_NOTIFICATIONS] = enableMailNotifications
}
}
suspend fun storeLastCheckedDate(lastCheckedDate: Long) {
dataStore.edit {
it[LAST_CHECKED_DATE] = lastCheckedDate

}
}
val lastCheckedDateFlow: Flow<Long> = dataStore.data.map {
it[LAST_CHECKED_DATE] ?: 0
}

val enableNotificationsFlow: Flow<Int> = dataStore.data.map {
it[ENABLE_NOTIFICATIONS] ?: 1
}
val enableMailNotificationsFlow: Flow<Int> = dataStore.data.map {
it[ENABLE_MAIL_NOTIFICATIONS] ?: 1
}

}

对于简单的工作来说,这是一个巨大的线程混乱。(永远不要让线程休眠以等待值(

如果你打算在工人阶级中使用协同作业。所以不要做

有一个替代的CoroutineWorker来扩展您的类,而不是Worker

它将为您提供doWork()功能的暂停版本

注意:记得添加工作管理器依赖项的-ktx版本

最新更新