我有一个允许用户进行多次下载的应用。
我的问题是#3,如果用户按下该键,而Asynctask丢失UI,则进度更新将在恢复时停止。由于该功能是多次并行下载,我如何获取正在下载的正确项目的更新?
当前,我将AsyncTask包装在一个片段中以保留实例。任何人都可以建议这样做的正确方法是什么(尽可能减少内存泄漏)?
class DownloadTaskFragment : Fragment() {
private var mCallbacks: TaskCallbacks? = null
private var mTask: DummyTask? = null
interface TaskCallbacks {
fun onPreExecute()
fun onProgressUpdate(progress: Int)
fun onCancelled()
fun onPostExecute()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
retainInstance = true
mTask = DummyTask(this)
mTask!!.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
}
fun setCallBackInterface(taskCallback: TaskCallbacks) {
mCallbacks = taskCallback
}
override fun onDetach() {
super.onDetach()
mCallbacks = null
}
class DummyTask// only retain a weak reference to the activity
internal constructor(context: DownloadTaskFragment) : AsyncTask<String, Int, Int>() {
private val reference: WeakReference<DownloadTaskFragment> = WeakReference(context)
private var mCallbacks: TaskCallbacks? = reference.get()!!.mCallbacks
override fun onPreExecute() {
if (mCallbacks != null) {
mCallbacks!!.onPreExecute()
}
}
override fun doInBackground(vararg params: String?): Int {
var i = 0
while (!isCancelled && i < 80) {
SystemClock.sleep(100)
publishProgress(i)
i++
}
return 1
}
override fun onProgressUpdate(vararg values: Int?) {
super.onProgressUpdate(*values)
if (mCallbacks != null) {
mCallbacks!!.onProgressUpdate(values[0]!!)
}
}
override fun onPostExecute(result: Int?) {
if (mCallbacks != null) {
mCallbacks!!.onPostExecute()
}
}
override fun onCancelled() {
if (mCallbacks != null) {
mCallbacks!!.onCancelled()
}
}
}
}
答案 0 :(得分:0)
为了确保任务在后台继续执行(尤其是在API 26+中增加了限制),您将需要创建foreground service。注意:您必须显示随附的通知(可以只是进度条)
作为前台服务,您的任务将与主UI分开运行,因此不会受到UI更改的影响。您也可以从服务中更新UI(有关更多信息,请参见here)
答案 1 :(得分:0)
为此,我强烈建议使用WorkManager。 可以在here中找到使用它的准则。
如果需要在WorkManager和Fragment之间进行通信,则可以使用LiveData<T>
。
Here是描述案件的文章。