当前位置: 代码迷 >> 综合 >> NO.1 Jetpeck 前言
  详细解决方案

NO.1 Jetpeck 前言

热度:47   发布时间:2023-12-15 16:19:07.0

零蚀


什么是Jetpack

  • 前言

    • 最快的学习一门技术,就是官方文档,所以首先我会贴出官方文档,(当然排除人民币玩家,和白?人员,但是这样不好,会非常依赖资源)[? Jetpack官方文档]

    • jetpack 既然说是一个工具,它主要从事的方面在:1、兼容java和kotlin(基础),2、架构,3、行为,4、界面(官方文档上都有)。而今天我要学习的顺序是2、3、4、1。基础里面包含监听测试等内容,所以后面用到再说。这一篇学习的就是jetpack的架构内容。


绑定简介

  • 视图绑定

    • 首先它的库是存在于google()中的,如果项目里面没有这个,需要添加。视图绑定就是viewBinding

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dleUGxI6-1590550000434)(media/15904601085683/15904614693885.jpg)]

    • 这里的库的版本我选择最近的稳定版本2.2.0

      implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
      
    • 我们可以添加视图绑定功能,当然我们可以用tools:viewBindingIgnore="true"来忽略视图的绑定。这种绑定是通过xml中的id进行引用,如果空间是没有id也就不会

      
      android {...viewBinding {enabled = true}
      }
      
    • 我们的布局会自动生成binding类比如说我的布局叫做activity_main.xml那么会自动生成ActivityMainBinding,我们通过它可以获取root,也就是xml的根布局,也能通过布局里面的id来获取对象的引用。

      class MainActivity : AppCompatActivity() {
              lateinit var binding: ActivityMainBinding;override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)binding = ActivityMainBinding.inflate(layoutInflater);setContentView(binding.root)// bind引用布局id来进行调用,// binding.root 这种getRoot方法也可以调用它的根布局binding.button.text="按钮"binding.button.setOnClickListener {
              Toast.makeText(this@MainActivity,"a",Toast.LENGTH_SHORT).show()}        }
      }
  • 数据绑定

    • 这里是利用dataBinding来实现数据的绑定首先我们还是要配置我们的gradle。

      android {...dataBinding {enabled = true}
      }
      
    • 我们准备了一个UserBean,然后xml里面的数据就直接绑定了这个数据,然后我们的布局需要在layout的标签之下的,layout里面分为两个部分,首先是的数据部分,然后是绘制的图层部分。

      <layout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"><data><variablename="viewModel"type="com.example.jetpackapplication.bean.UserBean" /></data><androidx.constraintlayout.widget.ConstraintLayout....><TextView.....android:text="@{viewModel.textContent}"..... /><Button......android:text="@{viewModel.buttonName}"....../></androidx.constraintlayout.widget.ConstraintLayout></layout>
      
    • 当然有列表的情况下我们可以直接获取对应的item

      …
      android:text="@{list[index]}"
      …
      android:text="@{sparse[index]}"
      …
      android:text="@{map[key]}"
      
    • 或者我们可以这么用,将type提出来。

      <data><import type="com.example.jetpackapplication.bean.UserBean"/><variablename="viewModel"type="UserBean" />
      </data>
      
    • 当然我们的UserBean里面的默认值是不会直接加载到我们的布局控件里的,只有我们设置数据的时候才会传数据给布局控件(这个后面说),我们可以在布局里可以直接设置它的默认值,但是这个默认值它只支持字母,汉子,下划线。不能使用特殊符号甚至是空格,且它的作用只是在预览的时候有效,运行的时候不会提供默认值给View

      android:text="@{viewModel.textContent,default=hello_jetpack}"
      
    • 接下来就是将数据绑定到我们的应用上,就是通过binding把数据绑定到控件上。这个流程和databinding的流程一致。

      // dataBean
      data class UserBean(val buttonName:String="new按钮",val textContent:String="jetPack")
      // MainActivity
      binding.viewModel= UserBean()
      

LiveData初涉

  • 使用

    • livedata是一种可观察的数据对象,但不同的是它具有生命周期感知的能力,他只会通知生命周期活跃的观察者,那些注册非活跃的则不会被通知,它的注册对象要实现LifecycleOwner才可以与之匹配。当相应的Lifecycle的状态未DESTROYED的时候,可以移除观察者。

    • 它的优势:1、可以动态调整数据更改的时机,2、自我清理,不会发生内存泄露,3、不会因 Activity 停止而导致崩溃,4、不再需要手动处理生命周期,5、数据始终保持最新状态,6、适当的配置更改,7、共享资源。

    • 应用场景:比如我们使用计时的时候,页面突然重新创建,我们发现及时任然存在,但是页面更新了,这是因为横竖屏切换重新走了onCreate方法。

      binding.button.setOnClickListener {Thread {while (index < 200) {SystemClock.sleep(1000)runOnUiThread {binding.text.text = "" + indexToast.makeText(this@MainActivity,""+index,Toast.LENGTH_SHORT).show()}}}.start()
      }
      

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kZyGDdXo-1590550000435)(media/15904601085683/bug.gif)]

    • 我们可以如下,将数据包含进一个LiveData且这个类必须继承自ViewMode。

      class UserViewMode :ViewModel(){
              // 创建一个UserBean的LiveDataval firstContent:MutableLiveData<UserBean> by lazy {
              MutableLiveData<UserBean>()}
      }
      
    • 然后我们通过ViewModelProvider将数据储存的持有者设置为我们的Activity(this),然后得到我们的ViewModel,再将我们的ViewModel和控件的数值绑定。

      binding.button.setOnClickListener {
              Thread {
              while (index < 200) {
              SystemClock.sleep(1000)//子线程里可以这么调用 mode.firstContent.postValue(UserBean("",""))runOnUiThread {
              index++mode.firstContent.value= UserBean("按钮",""+index)}}}.start()
      }mode=ViewModelProvider(this).get(UserViewModel::class.java)
      bindObserver()/*** 绑定*/private fun bindObserver(){
              val contentObserver = Observer<UserBean> {
              binding.text.text = it.textContentbinding.button.text = it.buttonName}mode.firstContent.observe(this, contentObserver)
      }
      

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nvFi5yeo-1590550000436)(media/15904601085683/solution.gif)]

    • 这里的this,不是指activity这个类,而是实现了ViewModelStoreOwner,而我们的AppCompactActivty早已实现了这个接口(父类)。这里的MutableLiveData也是LiveData,但是它屏蔽了她的所有的方法,除了值的设置,有兴趣可以自己继承viewMode来看看它的生命周期是否是在acitvity监听activity的生命周期下。


? 前言
? Android 知识栈
? Android Jetpack 系列