Jetpack

257 阅读2分钟

Jetpack

架构

使用示例

build.gradle

android {
    ···
    dataBinding {
        enabled = true
    }
}
dependencies {
    ···
    implementation "androidx.fragment:fragment-ktx:$rootProject.fragmentVersion"
    implementation "androidx.lifecycle:lifecycle-extensions:$rootProject.lifecycleVersion"
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$rootProject.lifecycleVersion"
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$rootProject.lifecycleVersion"
}

fragment_plant_detail.xml

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="viewModel"
            type="com.google.samples.apps.sunflower.viewmodels.PlantDetailViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            ···
            android:text="@{viewModel.plant.name}"/>

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

PlantDetailFragment.kt

class PlantDetailFragment : Fragment() {

    private val args: PlantDetailFragmentArgs by navArgs()
    private lateinit var shareText: String

    private val plantDetailViewModel: PlantDetailViewModel by viewModels {
        InjectorUtils.providePlantDetailViewModelFactory(requireActivity(), args.plantId)
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val binding = DataBindingUtil.inflate<FragmentPlantDetailBinding>(
                inflater, R.layout.fragment_plant_detail, container, false).apply {
            viewModel = plantDetailViewModel
            lifecycleOwner = this@PlantDetailFragment
        }

        plantDetailViewModel.plant.observe(this) { plant ->
            // 更新相关 UI
        }

        return binding.root
    }
}

Plant.kt

data class Plant (
    val name: String
)

PlantDetailViewModel.kt

class PlantDetailViewModel(
    plantRepository: PlantRepository,
    private val plantId: String
) : ViewModel() {

    val plant: LiveData<Plant>

    override fun onCleared() {
        super.onCleared()
        viewModelScope.cancel()
    }

    init {
        plant = plantRepository.getPlant(plantId)
    }
}

PlantDetailViewModelFactory.kt

class PlantDetailViewModelFactory(
    private val plantRepository: PlantRepository,
    private val plantId: String
) : ViewModelProvider.NewInstanceFactory() {

    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        return PlantDetailViewModel(plantRepository, plantId) as T
    }
}

InjectorUtils.kt

object InjectorUtils {
    private fun getPlantRepository(context: Context): PlantRepository {
        ···
    }

    fun providePlantDetailViewModelFactory(
        context: Context,
        plantId: String
    ): PlantDetailViewModelFactory {
        return PlantDetailViewModelFactory(getPlantRepository(context), plantId)
    }
}

Jetpack介绍

背景

App研发朝简单化、易上手发展。推出Android Jetpack让开发者按照模板式开发,让Bug减少,让开发者的精力放在打造应用本身。 可以很方便实现MVVM

好处

  • 消除大量重复样板式的代码。
  • 简化复杂的任务。
  • 提供了强健的向后兼容的能力。
  • 加速Android的开发进程。

JetPack的组成

四部分:Architecture、UI、Foundation、Behavior

  • Foundation:基础
  • Architecture:体系结构
  • UI:视觉交互
  • Behavior:行为

Android Jetpack采用组件化的方式。

Architecture Compinents(结构组件)

  • Data Binding(数据绑定)
  • Room(数据库)
  • WorkManager(后台任务管家)
  • Lifecycle(生命周期)
  • Navigation(导航)
  • Paging(分页)
  • LiveData(底层数据通知更改视图)
  • ViewModel(以注重生命周期的方式管理界面的相关数据)

Foundation(基础)

  • AppCompat(向后兼容)
  • Android KTX(编写更加简洁的Kotlin代码)
  • Multidex(多处理dex的问题)
  • Test(测试)

Behavior(行为)

  • Download manager(下载管理器)
  • Media & playback(媒体和播放)
  • Notification(通知)
  • Permissions(权限)
  • Preferences(偏好设置)
  • Sharing(共享)
  • Slices(切片)

UI(视觉交互)

  • Animation & transitions(动画和过渡)
  • Auto(Auto组件)
  • Emoji(表情)
  • Fragment(碎片)
  • Layout(布局)
  • Palette(调色板)
  • TV(TV)
  • Wear OS by Google(穿戴设备)

问题

"ViewDataBinding.getRoot() on a null object reference"

组件化开发的时候,报上面这个问题。

解决:

  1. 宿主src的包名与组件下src的包名不能一样
  2. 宿主对组件要用implementation,而不是runtime

...DataBinderMapperImpl.java:9: 错误: 找不到符号

D:\code\MyTests\MVVMDemo\app\build\generated\ap_generated_sources\debug\out\com\ab\mvvmdemo\DataBinderMapperImpl.java:9: 错误: 找不到符号
import com.ab.mvvmdemo.databinding.ActivityMainBindingImpl;
                                  ^
  符号:   类 ActivityMainBindingImpl
  位置: 程序包 com.ab.mvvmdemo.databinding

解决:十有八九是xml报错了。“排除法”排查xml的错误

ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication()).create(UserViewModel.class); 报 RuntimeException

解决:在此处断点,跟进去看具体报错【最后发现是关联的其他的实例需要在MyApplication中获取。而MyApplication没有在清单中进行实例化导致的】