How to avoid occurring many AsyncTask class in my Android Room repository?

我的未来我决定 提交于 2021-02-07 04:19:21

问题


I'm learning how to use Android Room from google-developer-training, where I found example of repository class. I try to simplify my SportRepository class. I wonder how to avoid repetition of inner class ...AsyncTask in my code. Here is very sample example:

@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
        }
    }
}

The AsyncTask classes differ only in name and in kind of method invoke from sportDAO class.

Is there any way to avoid creating many almost the same AsyncTask classes?

I've not found any example how to simplify that.


回答1:


Ok, I faced the same. There are 3 solutions that I use. 1. Use RX. Return a Flowable, and observe it on different thread. 2. Use LiveData. 3. Async Task. This is how I avoid multiple async tasks by using Generics. I hope this is what you are looking for.

This is the class that will perform your queries.

/**
 *
 * @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);
        }
    }
}

Now for querying

fun putAllUsersAsync(vararg users: User) {
            object : DaoAsyncProcessor<Unit>(null) {
                override fun doAsync(): Unit {
                    yourDao.insertAll(*users)
                }

            }.start()
        }

Another example of fetching data.

fun getAllUsers(callback: DaoAsyncProcessor.DaoProcessCallback<List<User>>) {
            object : DaoAsyncProcessor<List<User>>(callback) {
                override fun doAsync(): List<User> {
                    return yourDao.getAll()
                }

            }.start()

You can call getAllUsers and pass a callback for getting the data.

As requested, this is the Kotlin equivalent

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)
        }
    }
}



回答2:


Using RX java you could replace AsyncTask with a Completable for your insert/update/delete commands.

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) }



回答3:


You could use the same AsyncTask for each task if you pass it the code segment that it needs to actually execute.

You could for example do the following, using lambda-with-receivers (and without having to add Rx completables/singles or whatever):

@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
        }
    }
}


来源:https://stackoverflow.com/questions/49520123/how-to-avoid-occurring-many-asynctask-class-in-my-android-room-repository

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!