我正在使用 Kotlin Android Extension 直接通过 ID 访问 View 。 我有一个进度条,我使用 id 在 fragment 中直接访问它,即 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"/>
在 fragment 中,我用这段代码显示和隐藏它
progress_bar.visibility = if (visible) View.VISIBLE else View.GONE
在我旋转屏幕之前,它工作得很好。之后,它抛出异常
java.lang.IllegalStateException: progress_bar must not be null.
变量在屏幕旋转时变为空。如何解决这个问题?
fragment 代码
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()
}
}
重现步骤:
- 开始 Activity
- fragment 加载完毕
- 在 fragment 加载时,我加载一个 URL 并显示一个进度条
- 在加载 URL 时,我旋转手机,进度条变量变为空
最佳答案
在我的例子中,这个错误时有发生。当然,onViewCreated()
是放置代码的好方法。但奇怪的是,有时它还不够。 setRetainInstance(true)
可能有帮助,也可能没有。所以有时这会有所帮助:使用 view
变量访问您的 View
。您甚至可以在 onCreateView()
中访问它们。您可以使用 ?.
来保证应用程序不会崩溃(当然,在这种情况下某些 View 不会更新)。如果你想获得 context
,请使用 view.context
。
在我的例子中,这个错误只在 Kotlin 协程中重现。
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 - View 实例在屏幕旋转时变为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49050954/