簡體   English   中英

如何重用Dagger2注入的AsyncTask?

[英]How to reuse AsyncTask that is injected by Dagger2?

在片段的onStart方法中,片段調用演示者以獲取天氣數據。 演示者啟動一個AsyncTask ,該AsyncTask提取數據,將其返回給演示者,並顯示在片段中。 問題是,如果我打開片段(並獲取數據),切換到另一個活動,然后返回到片段,則會出現以下錯誤:

Caused by: java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once)
at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:605)
at android.os.AsyncTask.execute(AsyncTask.java:560)
at com.dev.weather.forecast.ForecastPresenter.fetchWeather(ForecastPresenter.kt:20)
at com.dev.weather.forecast.ForecastFragment.refreshWeather(ForecastFragment.kt:83)
at com.dev.weather.forecast.ForecastFragment.onStart(ForecastFragment.kt:105)
at android.support.v4.app.Fragment.performStart(Fragment.java:2287)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1458)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1750)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1819)
at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3227)
at android.support.v4.app.FragmentManagerImpl.dispatchStart(FragmentManager.java:3186)
at android.support.v4.app.FragmentController.dispatchStart(FragmentController.java:203)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:582)
at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:177)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1256)
at android.app.Activity.performStart(Activity.java:6959)
at android.app.Activity.performRestart(Activity.java:7075)
at android.app.Activity.performResume(Activity.java:7080)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3768)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3832) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1681) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:154) 
at android.app.ActivityThread.main(ActivityThread.java:6682) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)

在切換到Dagger之前我沒有這個問題,但是現在Dagger只創建了一個AsyncTask實例,但我不知道如何解決它。

我希望有人能幫助我!

分段:

@ActivityScoped
class ForecastFragment @Inject constructor(): DaggerFragment(), ForecastContract.View {

    @Inject
    lateinit var presenter: ForecastContract.Presenter

    override fun refreshWeather() {
        ...
        presenter.fetchWeather(location, unitType)
    }

    override fun onStart() {
        super.onStart()
        refreshWeather()
    }
}

主持人:

@ActivityScoped
class ForecastPresenter @Inject constructor() : ForecastContract.Presenter, FetchWeatherTask.AsyncResponse {

    @Inject
    lateinit var fetchWeatherTask: FetchWeatherTask

    override fun fetchWeather(location: String, unitType: String) {
        fetchWeatherTask.execute(location, unitType)
    }
    ...
}

AsyncTask:

class FetchWeatherTask @Inject constructor(private var client: OkHttpClient): AsyncTask<String, Void, MutableList<String>>() {
    ...
    override fun onPostExecute(result: MutableList<String>) {
        returnWeather()
    }
}

您的AsyncTask與您的ForecastFragment生命周期相關。 只要您的片段存在,您將擁有fetchWeatherTask的相同實例。

您不應該注入任務。 相反,每次需要時都創建一個新的。

如前所述,您不能重用AsyncTask,因此您不應直接注入它。

您可以做的是注入Provider<FetchWeatherTask> ,每次調用provider.get()時,它都會創建一個新任務,只要不限制作用域,在這種情況下,您總是會得到相同的對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM