IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> android_jetpack_代码重构之fragment基类 -> 正文阅读

[移动开发]android_jetpack_代码重构之fragment基类

代码重构之美

随着代码量增多,越来越觉得有必要构建fragment基类,今天实在受不了,于是重构开始…

注入viewmodel

实际上是要真正意义上对viewmodel进行自动注入的,由于我使用的是viewmodelFactory需要传参所以这里没有实现注入

BaseVmFragment.kt

package com.example.module_main.base

import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel

//虽然没法注入viewmodel但是可以使写法一眼知道碎片对应的ViewModel是什么
abstract class BaseVmFragment<VM: ViewModel>: Fragment() {
    //这里的VM并没有实际意义,没有使用到,仅仅用于可观性,让人一眼就知道碎片所对应的viewmodel
    lateinit var mActivity: AppCompatActivity


    //这个属性用来是否处理 使用jetpack navigation组件导航后,fragment是否重新执行onCreateView方法,重新执行就要重新初始化,之前初始化的状态丢失
    abstract var isHandleFragmentAgainOnCreateView: Boolean

    protected var isNavigationViewInit = false//记录是否已经初始化过一次视图
    protected var lastView: View? = null//记录上次创建的view

    //在Fragment直接只用getActivity()获得上下文有时会得到空引用,所以需要重写onAttach方法拿到上下文
    override fun onAttach(context: Context) {
        super.onAttach(context)
        mActivity = activity as AppCompatActivity
        onFragmentAttach()
    }

    /*
    * 在fragment 贴附时执行的方法,其实就是onAttach()罢了,只不过我们想要原来的onAttach方法获取上下文对象罢了
    * */
    abstract fun onFragmentAttach()

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? = inflater.inflate(layoutId(),container,false)

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

        if(isHandleFragmentAgainOnCreateView){
            if(!isNavigationViewInit){
                init(savedInstanceState)
                isNavigationViewInit = true
            }
        }else{
            init(savedInstanceState)
        }
    }



    fun init(savedInstanceState: Bundle?){

        initBeforeBinding(savedInstanceState)
        initBinding(savedInstanceState)
        initAfterBinding(savedInstanceState)
    }

    /*
    * 可以初始化自己想要的设置
    * */
    abstract fun initAfterBinding(savedInstanceState: Bundle?)

    /*
    * 可以初始化如容器转换的设置
    * */
    abstract fun initBeforeBinding(savedInstanceState: Bundle?)

    /*
    * 初始化绑定事件
    * */
    abstract fun initBinding(savedInstanceState: Bundle?)


    /*
    * 布局资源如R.layout.fragment_test
    * */
    abstract fun layoutId(): Int
}

注入DataBinding

BaseVmDbFragment.kt

package com.example.module_main.base

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.lifecycle.ViewModel

//自动注入viewmodel和databinding
abstract class BaseVmDbFragment<VM : ViewModel, DB : ViewDataBinding> : BaseVmFragment<VM>() {
    private var _binding: DB? = null
    val mBinding: DB get() = _binding!!

    //这个属性用来是否处理 使用jetpack navigation组件导航后,fragment是否重新执行onCreateView方法,重新执行就要重新初始化,之前初始化的状态丢失
    abstract override var isHandleFragmentAgainOnCreateView: Boolean


    //注意这里重写方法会直接覆盖BaseVmFragment,因此不用担心BaseVmFragme里onCreateView方法下实现的方法有影响
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        if (isHandleFragmentAgainOnCreateView) {
            //通过这种方式解决解决Android jetpack导航组件Navigation返回Fragment重走onCreateView方法刷新视图的问题
            if (lastView == null) {
                _binding = DataBindingUtil.inflate(inflater, layoutId(), container, false)
                //mBinding.lifecycleOwner = this
                // 因为这里和数据相关联着,所以这行一定要注释,否则会出现崩溃,这行正确做法应该放到onViewCreated()方法中!!!
                lastView = mBinding.root
            }
            return lastView
        } else {
            _binding = DataBindingUtil.inflate(inflater, layoutId(), container, false)
            mBinding.lifecycleOwner = this
            lastView = mBinding.root
            return lastView
        }



    }


    override fun onDestroy() {
        super.onDestroy()
        onFragmentDestroy()
        _binding = null
    }

    //- - - 注意以下两个方法除非是特殊需要否则直接覆盖后不执行操作即可!!!之所以把方法暴露出来是为了防止有特殊需求 ^.^

    /*
    * 在fragment销毁时执行的方法,其实就是onDestroy()罢了,只不过我们想要原来的onDestory()方法执行_binding = null操作而已
    * */
    abstract fun onFragmentDestroy()

    /*
    * 在fragment 贴附时执行的方法,其实就是onAttach()罢了,只不过我们想要原来的onAttach方法获取上下文对象罢了
    * */
    abstract override fun onFragmentAttach()

}

fragment基类的创建

BaseFragment.kt

package com.example.module_main.base

import android.os.Bundle
import androidx.databinding.ViewDataBinding
import androidx.lifecycle.ViewModel

//创建这个类没有实际作用,主要就是为了看起来好看,暴露所有需要或者重要的方法给使用者看, 老强迫症了
abstract class BaseFragment<VM: ViewModel, DB: ViewDataBinding>: BaseVmDbFragment<VM, DB>(){
    //- - - 注意以下onFragmentDestroy和onFragmentAttach两个方法通常覆盖后不操作!!!   之所以把方法暴露出来是为了防止有特殊需求 ^.^
    //- - - layoutId方法必须覆盖!!!


    /*
    * 这个属性用来是否处理 使用jetpack navigation组件导航后,fragment是否重新执行onCreateView方法,重新执行就要重新初始化,之前初始化的状态丢失
    * 为false表示不处理fragment重新初始化
    * 为true表示处理fragment重新初始化
    * */
    abstract override var isHandleFragmentAgainOnCreateView: Boolean

    /*
    * 在fragment销毁时执行的方法,其实就是onDestroy()罢了,只不过我们想要原来的onDestory()方法执行_binding = null操作而已
    * 在onDestory()方法内执行
    * */
    abstract override fun onFragmentDestroy()

    /*
    * 在fragment 贴附时执行的方法,其实就是onAttach()罢了,只不过我们想要原来的onAttach方法获取上下文对象罢了
    * 在onAttach()方法内执行
    * */
    abstract override fun onFragmentAttach()

    /**
     * 当前Fragment绑定的视图布局
     */
    abstract override fun layoutId(): Int


    /**
     * Fragment执行onViewCreated后触发,可以初始化如容器转换的设置,如果没有容器转换或fragment的进出动画要设置可以不初始化这个方法内容
     * 在initBinding方法前调用
     */
    abstract override fun initBeforeBinding(savedInstanceState: Bundle?)

    /*
    * 初始化绑定事件
    * */
    abstract override fun initBinding(savedInstanceState: Bundle?)

    /*
    * 初始化除了绑定操作外用户想自己定义的内容
    * 在initBinding方法后调用
    * */
    abstract override fun initAfterBinding(savedInstanceState: Bundle?)
}

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-10-18 17:30:27  更:2021-10-18 17:32:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:23:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码