Android-视图实例在屏幕旋转时为空 [英] Android - View instance gets null on screen rotation

查看:149
本文介绍了Android-视图实例在屏幕旋转时为空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Kotlin Android扩展程序通过其ID直接访问视图. 我有一个进度条,可以使用id直接访问片段,即progress_bar

I am using Kotlin Android Extension to access view directly by their id. I have a progress bar which I access directly in fragment using id i.e progress_bar

<ProgressBar
    android:id="@+id/progress_bar"
    style="@style/Widget.AppCompat.ProgressBar.Horizontal"
    android:layout_width="match_parent"
    android:layout_height="15dp"
    android:indeterminate="true"/>

在片段中,我正在使用此代码显示和隐藏它

In fragment, I am showing and hiding it with this code

progress_bar.visibility = if (visible) View.VISIBLE else View.GONE

在我旋转屏幕之前,它一直运行良好.之后,它会引发异常

It is working perfectly until I rotate the screen. After that, it throws the exception

java.lang.IllegalStateException:progress_bar不能为null.

java.lang.IllegalStateException: progress_bar must not be null.

该变量在屏幕旋转时为空.如何解决这个问题?

The variable gets null on screen rotation. How to solve this problem?

片段代码

class SingleAppFragment : Fragment() {

private lateinit var appName: String

companion object {
    fun newInstance(appName: String = ""): SingleAppFragment {
        val fragment = SingleAppFragment()
        val args = Bundle()
        args.putString(Constants.EXTRA_APP_NAME, appName)
        fragment.arguments = args
        return fragment
    }
}

private var mListener: OnFragmentInteractionListener? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    appName = if (arguments != null && !arguments.getString(Constants.EXTRA_APP_NAME).isEmpty()) {
        arguments.getString(Constants.EXTRA_APP_NAME)
    } else {
        Constants.APP_NAME_FACEBOOK
    }
}

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
                          savedInstanceState: Bundle?): View? {
    return inflater!!.inflate(R.layout.fragment_single_app, container, false)
}

override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    initView()
    setEventListeners()
}

private fun initView() {
    var canShowSnackBar = true

    web_single_app.webViewClient = object : WebViewClient() {

        override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
            super.onPageStarted(view, url, favicon)
            showHideProgressBar(true)
            canShowSnackBar = true
        }

        override fun onPageFinished(view: WebView?, url: String?) {
            super.onPageFinished(view, url)
            showHideProgressBar(false)
        }

        override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) {
            web_single_app.stopLoading()
            if (canShowSnackBar) {
                mListener?.onErrorWebView()
                canShowSnackBar = false
            }
        }
    }
    web_single_app.settings.javaScriptEnabled = true
    web_single_app.loadUrl(Constants.APP_NAME_URL_MAP[appName])
}

private fun setEventListeners() {
    back_web_control.setOnClickListener({
        web_single_app.goBack()
    })
}

fun showHideProgressBar(visible: Boolean) {
    progress_bar_web_control.visibility = if (visible) View.VISIBLE else View.GONE
}

fun loadUrl(appName: String) {
    web_single_app.loadUrl(Constants.APP_NAME_URL_MAP[appName])
}

override fun onAttach(context: Context?) {
    super.onAttach(context)
    if (context is OnFragmentInteractionListener) {
        mListener = context
    }
}

override fun onDetach() {
    super.onDetach()
    mListener = null
}

interface OnFragmentInteractionListener {
    fun onErrorWebView()
}
}


复制步骤:

  1. 开始活动
  2. 片段加载
  3. 加载片段时,我加载一个URL并显示进度条
  4. 加载URL时,我旋转手机,进度栏变量为null

推荐答案

就我而言,此错误有时会发生.当然,onViewCreated()是放置代码的好方法.但是有时它不足以使它奇怪.而setRetainInstance(true)可能有帮助,可能没有帮助.因此有时这会有所帮助:使用view变量访问View.您甚至可以在onCreateView()中访问它们.您可以使用?.来确保应用程序不会崩溃(当然,在这种情况下某些视图不会更新).如果希望获取context,请使用view.context.

In my case this bug happens from time to time. Of course, onViewCreated() is a good method to place your code in. But sometimes it's strangely not enough. And setRetainInstance(true) may help, may not. So sometimes this helps: access your Views with a view variable. You can even access them inside onCreateView(). You can use ?. for a guarantee that an application won't crash (of course, some views won't update in this case). If you wish to get context, use view.context.

就我而言,此错误仅在Kotlin协程中复制.

In my case this bug reproduced only in Kotlin coroutines.

private fun showProgress(view: View) {
    view.progressBar?.visibility = View.VISIBLE
}

private fun hideProgress(view: View) {
    view.progressBar?.visibility = View.GONE
}

然后输入代码:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    showData(view)
}

private fun showData(view: View) {
    showProgress(view)
    adapter = SomeAdapter()
    adapter.setItems(items)
    val divider = SomeItemDecoration(view.context)
    view.recycler_view?.run {
        addItemDecoration(divider)
        adapter = this@SomeFragment.adapter
        layoutManager = LinearLayoutManager(view.context)
        setHasFixedSize(true)
    }
    hideProgress(view)
}

这篇关于Android-视图实例在屏幕旋转时为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆