2017-08-30 37 views
1

我需要做一些需要JobService中的上下文的後臺工作(我使用的是Firebase JobDispatcher之一,因爲我們支持api 16+)我讀過很多關於JobService和AsyncTasks的文章,但我無法找到任何關於如何將它們結合起來的優秀文章,如果你需要一個上下文。如何防止JobService使用的AsyncTask中的上下文泄漏

我JobService

import com.firebase.jobdispatcher.JobParameters; 
import com.firebase.jobdispatcher.JobService; 

public class AsyncJobService extends JobService { 

    @Override 
    public boolean onStartJob(JobParameters job) { 
     new AsyncWork(this, job).execute(); 
     return true; 
    } 

    @Override 
    public boolean onStopJob(JobParameters job) { 
     return false; 
    } 
} 

我的AsyncTask

import android.os.AsyncTask; 
import com.firebase.jobdispatcher.JobParameters; 
import com.firebase.jobdispatcher.JobService; 

class AsyncWork extends AsyncTask<Void, Void, Void> { 

    private JobService jobService; 

    private JobParameters job; 

    AsyncWork(JobService jobService, JobParameters job) { 
     this.jobService = jobService; 
     this.job = job; 
    } 

    @Override 
    protected Void doInBackground(Void... voids) { 
     // some work that needs context 
     return null; 
    } 

    @Override 
    protected void onPostExecute(Void aVoid) { 
     super.onPostExecute(aVoid); 
     // some work that needs context 
     jobService.jobFinished(job, false); 
    } 
} 

這給出了一個警告,在AsyncWork類的jobService屬性泄漏上下文對象。我明白爲什麼如果你傳遞一個Activity或Fragment是這種情況,但這是一個JobService,它應該存在,直到我調用jobFinished()。我做錯了什麼,或者我可以忽略警告?

+0

取消它? 「AsyncTask」背後的要點是在後臺工作完成後在主應用程序線程上工作。 「JobService」不應該在主應用程序線程上做任何事情。因此,請使用常規的'Thread'或某種形式的'Executor'。 – CommonsWare

+0

JobService正在用於下載我們appwidget的數據和圖像並更新appwidget。我一直認爲用新的RemoteViews更新AppWidget需要在UiThread上完成。這似乎是我的假設是不正確的,我確實不需要一個AsyncTask。我明天要試試一個普通的'Thread'。謝謝! – Sander

+0

不,你可以通過'AppWidgetManager'從後臺線程更新一個應用部件。你需要一個'Context',但它可以是'Application'單例,以免引入任何內存泄漏。 'AsyncTask'在一般情況下處於「出局」狀態,但它只能用於主UI(活動,片段)。 – CommonsWare

回答

1

您不能忽略該警告。因爲AsyncWork保留對Context的引用,所以只有在任務完成之後才能對Context進行GC調用:Context內存泄漏。有兩種解決方案:

  1. 使用長壽命的上下文,無論如何,應用程序上下文。
  2. 領帶異步任務的生活背景下的使用壽命,其持有的引用:你爲什麼要擺在首位使用`AsyncTask`在
+1

1.我不能使用應用程序上下文,因爲我需要調用onPostExecuted()中的jobFinished()函數來釋放喚醒鎖。 2.據我所知,asynctask與JobService的生命息息相關,因爲我在JobService的onStartJob()中返回true,並在onPostExecute()的末尾調用jobFinished()。在JobService中沒有onPause(),會調用onStopJob()中的cancel()以防止泄漏100%的時間,即使警告仍然存在? – Sander

+0

在這種情況下,「泄漏」意味着Android框架需要現在已經過時的Activity活動對象所使用的內存,但由於AsyncWork擁有引用,因此無法獲取它。我不明白你的用例的細節,但這是你需要預防的。您還需要知道,一旦調用了「onDestroy」,您作爲上下文傳遞的「Activity」不再處於一致狀態。 –

+0

我注意到'AsyncWork'不會返回任何東西。你有沒有考慮把整個混亂放入一個'IntentService'? –