Как обрабатывать функции комнаты в ContentProvider Android?Android

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Как обрабатывать функции комнаты в ContentProvider Android?

Сообщение Anonymous »

Я пытаюсь предоставить данные из SQLite с помощью библиотеки Room в ContentProvider, и мое приложение использует Hilt для внедрения зависимостей.

Код: Выделить всё

@Entity(tableName = "files")
data class FileEntity(
@PrimaryKey(autoGenerate = false)
val url: String,
val fileName: String
)

Код: Выделить всё

@Dao
interface FilesDao {
@Query(value = "SELECT * FROM files ORDER BY fileName")
suspend fun getFiles(): List
}

Код: Выделить всё

@Database(entities = [FileEntity::class], version = 1, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {
abstract val filesDao: FilesDao
}

Код: Выделить всё

@Module
@InstallIn(SingletonComponent::class)
object RoomModule {
@Provides
@Singleton
fun provideAppDatabase(
@ApplicationContext context: Context
): AppDatabase = Room.databaseBuilder(
context, AppDatabase::class.java, "app_database"
).build()

@Provides
@Singleton
fun provideFilesDao(
appDatabase: AppDatabase
): FilesDao = appDatabase.filesDao
}
С помощью приведенного выше кода я могу получить экземпляр FilesDao в классе DataSource и нормально выполнять вызовы через приостановленные функции. Например:

Код: Выделить всё

data class FileModel(
val url: String,
val fileName: String
)

Код: Выделить всё

interface FilesDataSource {
suspend fun getFiles(): List
}

class FilesDataSourceImpl @Inject constructor(
private val filesDao: FilesDao
) : FilesDataSource {
override suspend fun getFiles(): List{
val filesEntity = filesDao.getFiles()
return filesEntity.toFilesModel()
}

private fun List.toFilesModel() = map { fileEntity ->
FileModel(
url = fileEntity.url,
fileName = fileEntity.fileName
)
}
}
Чтобы передать экземпляр посредством внедрения зависимостей с помощью Hilt в ContentProvider, я знаю, что необходимо создать собственную EntryPoint. Например:

Код: Выделить всё

@EntryPoint
@InstallIn(SingletonComponent::class)
interface ContentProviderEntryPoint {
// var appDatabase: AppDatabase
var filesDao: FilesDao
}
В ContentProvider На данный момент у меня есть следующий код:

Код: Выделить всё

class MyProvider : ContentProvider() {
private val appContext: Context by lazy {
context?.applicationContext ?: throw IllegalStateException()
}

private val files: List by lazy {
val hiltEntryPoint = EntryPointAccessors.fromApplication(
context = appContext,
entryPoint = ContentProviderEntryPoint::class.java
)

hiltEntryPoint.filesDao.getFiles() // this is a suspend function and I have no idea how to deal...
}

override fun onCreate(): Boolean {
return true
}

override fun query(
uri: Uri,
projection: Array?,
selection: String?,
selectionArgs: Array?,
sortOrder: String?
): Cursor {
TODO()
}

override fun getType(uri: Uri): String {
TODO()
}

override fun openAssetFile(
uri: Uri,
mode: String
): AssetFileDescriptor? {
TODO()
}

override fun insert(
uri: Uri,
values: ContentValues?
): Uri = throw UnsupportedOperationException()

override fun delete(
uri: Uri,
selection: String?,
selectionArgs: Array?
): Int = throw UnsupportedOperationException()

override fun update(
uri: Uri,
values: ContentValues?,
selection: String?,
selectionArgs: Array?
): Int = throw UnsupportedOperationException()
}
Теперь у меня сомнения, как быть с приостановленной функцией внутри ContentProvider?
Дополнительно:

Я видел несколько примеров, когда в классе DAO создавалась новая функция (не приостановленная) для возврата курсора. Например:

Код: Выделить всё

@Dao
interface FilesDao {
@Query(value = "SELECT * FROM files")
fun getFilesCursor(): Cursor

// other suspend functions for datasource layer
}
Таким образом я могу вызвать новую функцию в ContentProvider, но Room выдает исключение:

Код: Выделить всё

class MyProvider : ContentProvider() {
private val appContext: Context by lazy {
context?.applicationContext ?: throw IllegalStateException()
}

private val filesCursor: Cursor by lazy {
val hiltEntryPoint = EntryPointAccessors.fromApplication(
context = appContext,
entryPoint = ContentProviderEntryPoint::class.java
)

hiltEntryPoint.filesDao.getFilesCursor()
}

override fun onCreate(): Boolean {
println(filesCursor) // just to see the output, but this throw an IllegalStateException
return true
}

// ...
}
java.lang.IllegalStateException: невозможно получить доступ к базе данных в основном потоке, поскольку это потенциально может заблокировать пользовательский интерфейс на длительный период времени.
Моя цель с помощью ContentProvider — предоставить стикеры (файлы) для WhatsApp. У меня уже есть рабочая версия приложения, которая считывает контент непосредственно из JSON-файла, следуя той же логике, что и Hilt, проблема в том, что теперь, когда я перехожу на Room который использует приостановленные функции Я не могу справиться с этой ситуацией.

Подробнее здесь: https://stackoverflow.com/questions/733 ... ntprovider
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»