销毁用户界面后恢复下载进度

时间:2019-02-22 02:32:29

标签: android kotlin android-asynctask

我有一个允许用户进行多次下载的应用。

  1. 例如,用户单击一个图标,出现一个片段开始下载,并通过每秒更新进度条来显示进度。
  2. 用户可以按下“后退”按钮,片段被破坏,并且可以单击另一个按钮,并行下载另一个项目。
  3. 如果用户返回单击第一个图标,并且下载仍在进行中,则要求自动显示进度条,以便用户知道尚未完成下载。

我的问题是#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()
            }
        }
    }

}

2 个答案:

答案 0 :(得分:0)

为了确保任务在后台继续执行(尤其是在API 26+中增加了限制),您将需要创建foreground service。注意:您必须显示随附的通知(可以只是进度条)

作为前台服务,您的任务将与主UI分开运行,因此不会受到UI更改的影响。您也可以从服务中更新UI(有关更多信息,请参见here

答案 1 :(得分:0)

为此,我强烈建议使用WorkManager。 可以在here中找到使用它的准则。

如果需要在WorkManager和Fragment之间进行通信,则可以使用LiveData<T>Here是描述案件的文章。