Представления, не обновленные от обратного вызова асинхронной задачи после изменения ориентации - PullRequest
0 голосов
/ 03 февраля 2019

У меня есть действие с фрагментом с retainedInstance = true, определенное в его методе onCreate (), фрагмент будет выполнять некоторые сетевые операции, а затем отправляет данные обратно в действие.

Это мой обратный вызовфункция

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()
        }
    }

Проблема заключается в том, что после того, как я поверну устройство, когдая получаю обратный вызов от асинхронной задачи, мои представления не обновляются, так как индикатор выполнения все еще виден, когда я устанавливаю progressBar.visibility = View.GONE

1 Ответ

0 голосов
/ 03 февраля 2019

ОК, теперь я вижу, что вы вызываете callback.updateUi() из функций asyncTask.Это вызывает проблему, потому что когда вы выполняете операции в асинхронном режиме, вы не в потоке пользовательского интерфейса.Чтобы избежать этой проблемы, вам нужно вызвать runOnUiThread () внутри вашей функции override fun updateUi(result: ArrayList<Person>?)() и окружить весь код, связанный с пользовательским интерфейсом, блоком runOnUiThread.

пример:

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()
            }
        }

    } 
...