Я учусь использовать Android Room из обучение разработчиков google, где я нашел пример repository class. Я пытаюсь упростить свой класс SportRepository. Интересно, как избежать повторения inner class ...AsyncTask в моем коде. Вот очень примерный пример:
@Singleton
class SportRepository {
val LOG_TAG = SportRepository::class.java.name
@Inject
lateinit var sportDAO: SportDAO
var list: LiveData<List<Sport>>
init {
App.app().appComponent()?.inject(this)
list = sportDAO.getAll()
}
fun insert(sport: Sport) {
insertAsyncTask().execute(sport)
}
fun update(sport: Sport){
updateAsyncTask().execute(sport)
}
fun delete(sport: Sport) {
deleteAsyncTask().execute(sport)
}
@SuppressLint("StaticFieldLeak")
private inner class insertAsyncTask() : AsyncTask<Sport, Void, Void>() {
override fun doInBackground(vararg p0: Sport): Void? {
sportDAO.insert(p0.get(0))
return null
}
}
@SuppressLint("StaticFieldLeak")
private inner class updateAsyncTask() : AsyncTask<Sport, Void, Void>() {
override fun doInBackground(vararg p0: Sport): Void? {
sportDAO.update(p0[0])
return null
}
}
@SuppressLint("StaticFieldLeak")
private inner class deleteAsyncTask() : AsyncTask<Sport, Void, Void>() {
override fun doInBackground(vararg p0: Sport): Void? {
sportDAO.delete(p0[0])
return null
}
}
}
Классы AsyncTask отличаются только именем и видом вызова метода от класса sportDAO.
Есть ли способ избежать создания множества почти одинаковых классов AsyncTask?
Я не нашел ни одного примера, как это упростить.
Хорошо, я столкнулся с тем же. Я использую 3 решения. 1. Используйте RX. Верните Flowable и наблюдайте за ним в другом потоке. 2. Используйте LiveData. 3. Асинхронная задача. Вот как я избегаю выполнения нескольких асинхронных задач с помощью Generics. Надеюсь, это то, что вы ищете.
Это класс, который будет выполнять ваши запросы.
/**
*
* @param <T> type of result expected
*/
public abstract class DaoAsyncProcessor<T> {
public interface DaoProcessCallback<T>{
void onResult(T result);
}
private DaoProcessCallback daoProcessCallback;
public DaoAsyncProcessor(DaoProcessCallback daoProcessCallback) {
this.daoProcessCallback = daoProcessCallback;
}
protected abstract T doAsync();
public void start(){
new DaoProcessAsyncTask().execute();
}
private class DaoProcessAsyncTask extends AsyncTask<Void, Void, T>{
@Override
protected T doInBackground(Void... params) {
return doAsync();
}
@Override
protected void onPostExecute(T t) {
if (daoProcessCallback != null)
daoProcessCallback.onResult(t);
}
}
}
Теперь для запроса
fun putAllUsersAsync(vararg users: User) {
object : DaoAsyncProcessor<Unit>(null) {
override fun doAsync(): Unit {
yourDao.insertAll(*users)
}
}.start()
}
Еще один пример получения данных.
fun getAllUsers(callback: DaoAsyncProcessor.DaoProcessCallback<List<User>>) {
object : DaoAsyncProcessor<List<User>>(callback) {
override fun doAsync(): List<User> {
return yourDao.getAll()
}
}.start()
Вы можете вызвать getAllUsers и передать обратный вызов для получения данных.
По запросу, это эквивалент Kotlin
abstract class DaoAsyncProcessor<T>(val daoProcessCallback: DaoProcessCallback<T>?) {
interface DaoProcessCallback<T> {
fun onResult(result: T)
}
protected abstract fun doAsync(): T
fun start() {
DaoProcessAsyncTask().execute()
}
private inner class DaoProcessAsyncTask : AsyncTask<Void, Void, T>() {
override fun doInBackground(vararg params: Void): T {
return doAsync()
}
override fun onPostExecute(t: T) {
daoProcessCallback?.onResult(t)
}
}
}
Это потому, что я думаю, что вы сделали его внутренним классом
Когда я пытаюсь преобразовать класс DaoAsyncProcessor, я застрял на проблеме с методом onPostExecute(T t). Я получаю сообщение от IDE: Out-projected type 'DaoAsyncProcessor.DaoProcessCallback<*>' prohibits the use of 'public abstract fun onResult(result: T): Unit. Пожалуйста, предоставьте код Kotlin для этого класса или расскажите, как решить эту проблему?
@wapn добавление эквивалента котлина
Используя RX java, вы можете заменить AsyncTask на Completable для ваших команд вставки / обновления / удаления.
fun insert(sport: Sport) : Completable = Completable.fromAction { sportDAO.insert(sport) }
fun update(sport: Sport) : Completable = Completable.fromAction { sportDAO.update(sport) }
fun delete(sport: Sport) : Completable = Completable.fromAction { sportDAO.delete(sport) }
Вы можете использовать одну и ту же AsyncTask для каждой задачи, если передадите ей сегмент кода, который она действительно должна выполнить.
Вы можете, например, сделать следующее, используя lambda-with-receivers (и без необходимости добавлять дополнения / синглы Rx или что-то еще):
@Singleton
class SportRepository @Inject constructor(val sportDAO: SportDao) {
companion object {
const val LOG_TAG = "SportRepository"
}
var list: LiveData<List<Sport>> = sportDAO.getAll() // is this necessary?
fun insert(sport: Sport) {
executeTask(sport) { insert(it) }
}
fun update(sport: Sport){
executeTask(sport) { update(it) }
}
fun delete(sport: Sport) {
executeTask(sport) { delete(it) }
}
private fun executeTask(sport: Sport, task: SportDao.(Sport) -> Unit) {
BackgroundTask(sport, task).execute()
}
@SuppressLint("StaticFieldLeak")
private inner class BackgroundTask(
private val sport: Sport,
private val task: SportDao.(Sport) -> Unit
) : AsyncTask<Void, Void, Void>() {
override fun doInBackground(vararg p0: Void): Void? {
task(sportDAO, sport)
return null
}
}
}
Мне нравится это решение, однако Android Studio говорит, что DaoProcessAsyncTask должен быть статическим.