方向更改后,视图未从asynctask的回调中更新

时间:2019-02-03 15:56:21

标签: android android-fragments kotlin android-asynctask

我有一个活动,在其onCreate()方法上定义了一个带有retainableInstance = true的片段,该片段将进行一些联网,然后将数据发送回该活动。

这是我的回调函数

override fun updateUi(result: ArrayList<Person>?) {
    progressBar.visibility = View.GONE
    window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
    if (result != null) {
        setAdapter(result)
    }
    else {
        finishNetworking()
        val snackBar = Snackbar.make(findViewById(R.id.root_layout),
            "Network failure", Snackbar.LENGTH_INDEFINITE)
        snackBar.setAction("Try again") {
            startDownload()
        }
        snackBar.show()
    }
}

这是我的活动onCreate()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    viewManager = LinearLayoutManager(this)
    progressBar = findViewById(R.id.progress_bar)
    recyclerView = findViewById<RecyclerView>(R.id.recycler_view).apply {
        setHasFixedSize(true)
        layoutManager = viewManager
    }

    if (savedInstanceState == null) {
        hasArgs = false
        networkFragment = NetworkFragment.getInstance(supportFragmentManager, SWAPI_URL_PEOPLE, null)
    }
    else {
        hasArgs = true
        networking = savedInstanceState.getBoolean("networking", false)
        if (networking) {
            window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
            progressBar.visibility = View.VISIBLE

        }
        if (savedInstanceState.getParcelableArrayList<Person>("persons") != null) {
            setAdapter(savedInstanceState.getParcelableArrayList<Person>("persons") as ArrayList<Person>)
        }
    }

}

这是我的AsyncTask

private class NetworkTask(
    callback: NetworkCallback<ArrayList<Person>>,
    person: Person?
)
    : AsyncTask<String, Int, NetworkTask.Result>() {

    private val mCallback: NetworkCallback<ArrayList<Person>>? = callback
    private val mPerson: Person? = person

    internal class Result {
        var mResultValue: ArrayList<Person>? = null
        var mException: Exception? = null

        constructor(resultValue: ArrayList<Person>?) {
            mResultValue = resultValue
        }

        constructor(exception: Exception) {
            mException = exception
        }
    }

    override fun onPreExecute() {

        if (mCallback != null) {

            if (Build.VERSION.SDK_INT < 23) {
                val networkInfo = mCallback.getConnectivityManager().activeNetworkInfo
                if (networkInfo?.isConnected == false
                    || networkInfo?.type != ConnectivityManager.TYPE_WIFI
                    && networkInfo?.type != ConnectivityManager.TYPE_MOBILE) {
                    mCallback.updateUi(null)
                    cancel(true)
                }
            }
            else {
                val network = mCallback.getConnectivityManager().activeNetwork
                val networkCapabilities = mCallback.getConnectivityManager().getNetworkCapabilities(network)
                if (networkCapabilities?.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) == false &&
                    !networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                    mCallback.updateUi(null)
                    cancel(true)
                }
            }
        }
    }

    override fun doInBackground(vararg urls: String): Result? {
        var result: Result? = null
        if (!isCancelled && urls.isNotEmpty()) {
            val urlString = urls[0]
            result = try {
                val resultString = downloadUrl(urlString)
                if (resultString != null) {
                    val persons = ArrayList<Person>()
                    if (mPerson == null) {
                        Result(getAllPersons(urlString, persons))
                    }
                    else {
                        persons.add(getPersonHomeworldAndVehicles(urlString, mPerson))
                        Result(persons)
                    }
                } else {
                    throw IOException("No response received.")
                }
            } catch (e: Exception) {
                Result(e)
            }

        }
        return result
    }


    override fun onPostExecute(result: Result?) {
        mCallback?.apply {
            result?.mException?.also { exception ->
                updateUi(null)
                return
            }
            result?.mResultValue?.also { resultValue ->
                updateUi(resultValue)
                return
            }
            finishNetworking()
        }
    }

问题是我旋转设备后,当我从asynctask收到回调时,我的视图没有更新,因为当我设置progressBar.visibility = View.GONE时,进度条仍然可见

1 个答案:

答案 0 :(得分:0)

好的,现在我看到您从asyncTask函数调用callback.updateUi()了。 这引起了问题,因为在异步任务中执行操作时,您处于非UI线程中。 为避免此问题,您需要在功能override fun updateUi(result: ArrayList<Person>?)()内调用runOnUiThread(),并用runOnUiThread块包围所有与UI相关的代码。

示例:

override fun updateUi(result: ArrayList<Person>?) {

        runOnUiThread {
            progressBar.visibility = View.GONE
            window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
            if (result != null) {
                setAdapter(result)
            } else {
                finishNetworking()
                val snackBar = Snackbar.make(findViewById(R.id.root_layout),
                        "Network failure", Snackbar.LENGTH_INDEFINITE)
                snackBar.setAction("Try again") {
                    startDownload()
                }
                snackBar.show()
            }
        }

    }