Как избежать появления большого количества классов AsyncTask в моем репозитории Android Room?

Я учусь использовать 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?

Я не нашел ни одного примера, как это упростить.

2
0
2 976
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Хорошо, я столкнулся с тем же. Я использую 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)
        }
    }
}

Мне нравится это решение, однако Android Studio говорит, что DaoProcessAsyncTask должен быть статическим.

BlackCath 23.05.2018 11:51

Это потому, что я думаю, что вы сделали его внутренним классом

Debanjan 23.05.2018 12:01

Когда я пытаюсь преобразовать класс DaoAsyncProcessor, я застрял на проблеме с методом onPostExecute(T t). Я получаю сообщение от IDE: Out-projected type 'DaoAsyncProcessor.DaoProcessCallback<*>' prohibits the use of 'public abstract fun onResult(result: T): Unit. Пожалуйста, предоставьте код Kotlin для этого класса или расскажите, как решить эту проблему?

wapn 12.07.2018 17:42

@wapn добавление эквивалента котлина

Debanjan 12.07.2018 21:20

Используя 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
        }
    }
}

Другие вопросы по теме