第一行代码 第三版 第五章 碎片

本文详细介绍了Android中Fragment的使用,包括静态和动态添加,以及如何在Fragment和Activity之间交互。同时,讲解了Fragment的生命周期,展示了不同状态下的回调方法,并通过示例代码演示了生命周期的变化过程。此外,还提及了Kotlin的扩展函数和运算符重载特性。
摘要由CSDN通过智能技术生成

第 5 章 碎片

5.2 碎片的使用方式

5.2.1 碎片的简单使用

  1. 编写 left_fragment.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="Button"
        />

</LinearLayout>

  1. 编写 right_fragment.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:background="#00ff00"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textSize="24sp"
        android:text="This is right fragment"
        />

</LinearLayout>

3.编写左侧碎片代码

class LeftFragment : Fragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.left_fragment,container,false)
    }
}
  1. 编写右侧碎片代码
class RightFragment : Fragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.right_fragment,container,false)
    }
}
  1. 编写主活动布局
<LinearLayout 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"
    android:layout_width="match_parent"
    android:orientation="horizontal"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <fragment
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:id="@+id/leftFrag"
        android:name="android.bignerdranch.fragmenttest.LeftFragment"
        />

    <fragment
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:id="@+id/rightFrag"
        android:name="android.bignerdranch.fragmenttest.RightFragment"
        />

</LinearLayout>

5.2.2 动态添加碎片

  1. 新建另一个右侧右侧布局 another_right_fragment.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:background="#ffff00"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textSize="24sp"
        android:text="This is another right fragment"
        />

</LinearLayout>

  1. 新建另一个右侧碎片代码
class AnotherRightFragment:Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.another_right_fragment,container,false)
    }
}
  1. 修改主布局
<LinearLayout 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"
    android:layout_width="match_parent"
    android:orientation="horizontal"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <fragment
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:id="@+id/leftFrag"
        android:name="android.bignerdranch.fragmenttest.LeftFragment"
        />

    <FrameLayout
        android:id="@+id/rightLayout"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        >
    </FrameLayout>

</LinearLayout>
  1. 编写主布局代码动态添加碎片
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        button.setOnClickListener{
            replaceFragment(AnotherRightFragment())
        }
        replaceFragment(RightFragment())
    }

    private fun replaceFragment(fragment: Fragment) {
        val fragmentManager = supportFragmentManager
        val transaction = fragmentManager.beginTransaction()
        transaction.replace(R.id.rightLayout, fragment)
        transaction.commit()
    }
}

5.2.3 碎片中实现返回栈

在提交事务之前调用

transaction.addToBackStack(null)

5.2.4 碎片和活动进行交互

  • 活动中调用碎片的方法
//fFBI 用于在布局中获取碎片的实例,然后就能使用里面的方法了
val fragment = supportFragmentManager.findFragmentById(R.id.leftFrag) as LeftFragment

优化 :id ‘kotlin-android-extensions’ 插件允许我们直接使用布局文件中定义的碎片 Id 来自动获取碎片的实例

val fragment = leftFrag as LeftFragment
  • 碎片中调用活动的方法
if (activity != null) {
    val mainActivity = activity as MainActivity
}

补充:得到的Activity本身就是一个Context对象

  • 碎片和碎片的通信

先在碎片中获取与它关联的活动,然后通过活动去获得另一个碎片

5.3 碎片的生命周期

5.3.1 碎片的状态和回调

  1. 状态
  • 运行状态:当一个活动进入运行状态时,相关联的碎片也会进入运行状态
  • 暂停状态:当一个活动进入暂停状态时,相关联的碎片也会进入暂停状态
  • 停止状态:当一个活动进入停止状态时,相关联的碎片也会进入停止状态。通过调用了事务的remove和replace方法,但是事务提交前调用了addToBackStack方法,也会进入停止状态。这时候的碎片完全不可见有可能被收回
  • 销毁状态:当一个活动进入销毁状态时,相关联的碎片也会进入销毁状态。通过调用了事务的remove和replace方法,但是事务提交前没有调用了addToBackStack方法,会进入销毁状态。
  1. 回调
  • onAttach( ) :碎片和活动建立关联时调用
  • onCreateView( ):碎片创建视图(加载布局)时调用
  • onActivityCreated( ):确保和碎片相关联的活动创建完毕时调用
  • onDestroyView( ):与碎片相关联的视图被移除时调用
  • onDetach( ):碎片和活动解除关联时调用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WBTxnkR4-1660713951648)(第一行代码Kotlin.assets/image-20220816215031973.png)]

5.3.2 体验碎片的生命周期

class RightFragment : Fragment() {

    //kotlin中定义常量都是在companion object、单例类、顶层作用域中使用
    companion object {
        const val TAG = "RightFragment"
    }

    override fun onAttach(context: Context) {
        super.onAttach(context)
        Log.d(TAG, "onAttach")
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d(TAG, "onCreate")
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        Log.d(TAG, "onCreateView")
        return inflater.inflate(R.layout.right_fragment, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        Log.d(TAG, "onActivityCreated")
    }

    override fun onStart() {
        super.onStart()
        Log.d(TAG, "onStart")
    }

    override fun onResume() {
        super.onResume()
        Log.d(TAG, "onResume")
    }

    override fun onPause() {
        super.onPause()
        Log.d(TAG, "onPause")
    }

    override fun onStop() {
        super.onStop()
        Log.d(TAG, "onStop")
    }

    override fun onDestroyView() {
        super.onDestroyView()
        Log.d(TAG, "onDestroyView")
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d(TAG, "onDestroy")
    }

    override fun onDetach() {
        super.onDetach()
        Log.d(TAG, "onDetach")
    }

}
  1. 刚进入 attach-create-createView-ActivityCreated-start-resume
  2. 点击左侧按钮 pause - stop - destroyView
  3. 如果没有加入返回栈 destroy - detach
  4. 按下back createView - activityCreated - start - resume//create没执行因为加入了返回栈,碎片没被销毁
  5. 再次按下back pause - stop - destroyView - destroy -Detach

5.4 动态添加布局的技巧

5.4.1 使用限定符

5.4.2 使用最小限定符

因为不常用到并且在第二版的时候实现过,就不再敲一遍,很简单,跟着书就能实现

5.5 简易版新闻应用 没实现

5.6 Kotlin 课堂:扩展函数和运算符重载

5.6.1 拓展函数

拓展函数:在不修改某个类的源码的情况下,仍然可以打开这个类,向该类新增新的函数

情景:统计字符串中的字母的数量

  • 定义单例类,在单例类中写方法
object StringUtil {
    
    fun letterCount(str: String): Int{
        var count = 0
        for (char in str) {
            if (char.isLetter()) {
                count++
            }
        }
        return count
    }
}
  • 拓展函数的语法结构 类名.方法就表示将方法定义到类里面
fun ClassName.methodName(param1: Int,param2:Int): Int{
	return 0
}
  • 应用:向String 中定义一个拓展函数

建议:向哪个类中定义拓展函数,就定义一个同名的 Kotlin 文件。定义成顶层方法,能够拥有全局的访问域

fun String.lettersCount():Int{
  	//因为拥有了String的上下文所以就不需要传入字符串,直接遍历this,this就是字符串本身
    var count = 0
    for (char in this) {
        if (char.isLetter()) {
            count++
        }
    }
    return count
}

调用

val count = "ABC123xyz!@#".lettersCount()

补充:String中有capitalize()实现首字母大写,reverse()字符串反转

5.6.2 运算符的重载

语法结构:在“指定函数”前加入operator关键字

class Obj{

	operator fun plus(obj: Obj): Obj{
		//处理相加的逻辑
	}
}
  • 调用
val obj1 = Obj()
val obj2 = Obj()
val obj3 = obj1 + obj2
//编译的时候就会转换成 obj1.plus(obj2)
  • 应用:实现两个Money相加
class Money(val value:Int) {
    operator fun plus(money:Money):Money{
        val sum = value + money.value
        return Money(sum)
    }
    
    //实现Money和数字的相加
    operator fun plue(newValue:Int):Money{
    	val sum = value + newValue
    	return Money(sum)
    }
}

//调用,在main函数中
val money1 = Money(5)
val money2 = Money(10)
val money3 = money1 + money2
val money4 = money3 + 20
println(money3.value)
println(money4.value)
语法糖表达式实际调用函数
a + ba.plus(b)
a - ba.minus(b)
a * ba.times(b)
a / ba.div(b)
a % ba.rem(b)
a++a.inc()
a–a.dec()
+aa.unaryPlus()
-aa.unaryMinus()
!aa.not()
a == ba.equals(b)
a > ba < ba >= b****a <= ba.compareTo(b)
a…ba.rangeTo(b)
a[b]a.get(b)
a[b] = ca.set(b, c)
a in bb.contains(a)

对随机生成字符串的函数进行优化

operator fun String.times(n:Int):String{
    val builder = StringBuilder()
    repeat(n){
        builder.append(this)
    }
    return builder.toString()
}
//调用
val str = "abc"*3
println(str)
//结果: abcabcabc

优化:Kotlin中的String已经拓展了一个重复字符串的方法

operator fun String.time(n:Int) = repeat(n)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小蒋的学习笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值