android使用androidx后可以使用viewbinding了,因为是内生库,也蛮好用的。
butterknife感觉已经在退环境了。
文章列出ViewModel + ViewBinding,是MVVM模式的简单使用,没有涉及到太复杂的环境,如果要在复杂环境下使用,还有待研究。
在Kotlin中使用ViewBinding需要的在build.gradle(APP)中启用:
android { ... buildFeatures { viewBinding true } }
这里使用的是一个使用Fragment载入网页的例子,使用ViewModel来给Fragment提供数据。涉及到的数据简单的认为有2个,一个是网页的URL,另外一个是网页的Title。我们用一个java bean来存放该数据,如下:
data class DataWeb(var title: String, var url: String)
接下来是用ViewMod提供数据的实现类:
class WebViewModel : ViewModel() { private val _general = MutableLiveData<Constants>().apply { value = DataWeb("baidu", "https://www.baidu.com") } val general get() = _general /** 改变*/ fun update(title: String?, url: String, showActionBar: Boolean = false) { val constants = general.value constants?.title = title ?: "" constants?.url = url general.value = constants } }
接下来是使用Fragment载入数据:
// 布局layout_fragment.xml <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <RelativeLayout android:id="@+id/actionBar" android:layout_width="match_parent" android:layout_height="56dp" android:background="@color/actionBarBackground" android:elevation="4dp"> <TextView android:id="@+id/tvActionBarTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginStart="20dp"/> </RelativeLayout> <com.scwang.smartrefresh.layout.SmartRefreshLayout android:id="@+id/refreshLayout" android:layout_width="match_parent" android:layout_height="match_parent"> <android.webkit.WebView android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="match_parent"/> </com.scwang.smartrefresh.layout.SmartRefreshLayout> </LinearLayout> </layout> // Fragment实现 class WebViewFragment2 : Fragment(), TheWebViewClientCallback, TheWebViewChromeClientCallback { companion object { const val TAG = "WebViewFragment" } private var _binding: LayoutFragmentBinding? = null // This property is only valid between onCreateView and // onDestroyView. val binding get() = _binding!! private lateinit var webViewModel: WebViewModel private var loadService: LoadService<Any>? = null /** 是否记载出错*/ private var isLoadError = false /** 支持下拉刷新*/ var canNativeRefresh = true /** 是否需要重新载入URL*/ var isNeedLoadUrl = true override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { webViewModel = ViewModelProvider(this).get(WebViewModel::class.java) _binding = LayoutFragmentBinding.inflate(inflater, container, false) val webView = binding.webView.apply { // 监控WebView载入的过程 webViewClient = TheWebViewClient().apply { callback = this@WebViewFragment2 } // 仅接受Title webChromeClient = TheWebViewChromeClient().apply { callback = this@WebViewFragment2 } settings.javaScriptEnabled = true } binding.refreshLayout.apply { // 无需加载更多 setEnableLoadMore(false) // 支持下拉刷新 setEnableRefresh(canNativeRefresh) setOnRefreshListener { webView.reload() } } webViewModel.general.observe(viewLifecycleOwner) { binding.tvActionBarTitle.text = it.title if (isNeedLoadUrl) { isNeedLoadUrl = false webView.loadUrl(it.url) } Log.d(TAG, "<---->observe called<---->") } loadService = LoadSir.getDefault().register(binding.refreshLayout) { // 用户点击按钮的reload事件 loadService?.showCallback(LoadingCallback::class.java) Log.d(TAG, "<>register loadService<>") webView.reload() } return binding.root } override fun pageStarted(url: String?) { Log.d(TAG, "<>pageStarted<>") isLoadError = false loadService?.showCallback(LottieLoadingCallback::class.java) } override fun pageFinished(url: String?) { Log.d(TAG, "<>pageFinished<>") if (!isLoadError) { loadService?.showSuccess() } binding.refreshLayout.setEnableRefresh(canNativeRefresh) binding.refreshLayout.finishRefresh() } override fun one rror() { Log.e(TAG, "<>onError<>") isLoadError = true loadService?.showCallback(ErrorCallback::class.java) } override fun onReceivedTitle(title: String?) { Log.d(TAG, "onReceivedTitle : $title") webViewModel.update(title, "") } }
ViewModel对数据的监控使用的是观察者模式,代码中webViewModel.general.observe()就是启用观察者,而且加入了lifecycle中来保证在生命周期中能够接受到数据的变更,初始数据的载入,也在general.observe()方法中实现。而实时数据的变更使用的是model中的我们自己写的update()方法。
以上就是本文要介绍的内容。
最后提出其他边角的代码:
interface TheWebViewClientCallback { fun pageStarted(url: String?) fun pageFinished(url: String?) fun one rror() } class TheWebViewClient : WebViewClient() { var callback: TheWebViewClientCallback? = null override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { super.onPageStarted(view, url, favicon) if (null != callback) { callback!!.pageStarted(url) } else { Log.e("TAG", "onPageStarted callback is null") } } override fun onPageFinished(view: WebView?, url: String?) { super.onPageFinished(view, url) callback?.pageFinished(url) } override fun onReceivedError( view: WebView?, request: WebResourceRequest?, error: WebResourceError? ) { callback?.onError() super.onReceivedError(view, request, error) } } interface TheWebViewChromeClientCallback { fun onReceivedTitle(title: String?) } class TheWebViewChromeClient : WebChromeClient() { var callback: TheWebViewChromeClientCallback? = null override fun onReceivedTitle(view: WebView?, title: String?) { super.onReceivedTitle(view, title) callback?.onReceivedTitle(title) } }
//三方框架
// loadSir
implementation 'com.kingja.loadsir:loadsir:1.3.8'
// lottie
implementation 'com.airbnb.android:lottie:5.2.0'
// 下拉刷新
implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0-andx-11'
标签:String,title,url,kotlin,ViewModel,binding,var,ViewBinding,fun From: https://www.cnblogs.com/swalka/p/16868876.html