首页 > 其他分享 >使用LiveData、ViewModel在Activity和Fragment,Fragment和Fragment之间共享数据

使用LiveData、ViewModel在Activity和Fragment,Fragment和Fragment之间共享数据

时间:2023-08-11 12:11:53浏览次数:39  
标签:Fragment mModel ViewModel ViewModelProvider Activity UserViewModel class

一、概述

  传统的Activity与Fragment之间共享数据,Fragment与Fragment之间共享数据,我一般会采用EventBus事件总线来实现。不过现在可以借助另外一种简单的方式LiveData+ViewModel也可以实现这种共享

二、代码示例

  示例描述:要求FragmentA发送出数据,FragmentB和Activity都能接收到。FragmentB发送出的数据FragmentA和Activity都能接收到。Activity发送出去的数据FragmentA和FragmentB都能接收到。

  上代码:

  SharedDataActivity.kt用于承载两个Fragment以及自己数据的Activity

/**
 * Activity和Fragment,Fragment和Fragment之间共享数据
 */
class ShareDataActivity :AppCompatActivity(){
    private var mModel:UserViewModel?=null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_share_data)
        //第一种实现方式
        mModel = ViewModelProvider(this,ViewModelProvider.AndroidViewModelFactory.getInstance(com.tony.demo.utils.ContextUtils.getApplicationContext())).get(UserViewModel::class.java)
        //第二种实现方式
//        mModel = ViewModelProvider(this).get(UserViewModel::class.java)
        supportFragmentManager.beginTransaction().replace(R.id.fl_continer1,FragmentA()).commit()
        supportFragmentManager.beginTransaction().replace(R.id.fl_continer2, FragmentB()).commit()

        btnSendToActivity.setOnClickListener {
            mModel?.getAccount()?.postValue(AccountBean("Activity的数据:杨洛峋",5))
        }

        mModel?.getAccount()?.observe(this){
            tvContentActivity.text = "接收到来自${it.name} ${it.age} 岁了!"
        }

    }
}

 activity_shared_data.layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:weightSum="3">

    <FrameLayout
        android:id="@+id/fl_continer1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1" />

    <FrameLayout
        android:id="@+id/fl_continer2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1" />

    <RelativeLayout
        android:id="@+id/fl_continer3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1">

        <Button
            android:id="@+id/btnSendToActivity"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Activity发送消息" />

        <TextView
            android:id="@+id/tvContentActivity"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="" />
    </RelativeLayout>
</LinearLayout>

FragmentA.kt

/**
 * 使用LiveData+ViewModel让A和B进行通信
 */
class FragmentA : Fragment(){
    private var mModel: UserViewModel? = null
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_a, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        //第一种实现方式
//        mModel = ViewModelProvider(requireActivity()).get(UserViewModel::class.java)
        //第二种实现方式
        mModel = ViewModelProvider(requireActivity(),
            ViewModelProvider.AndroidViewModelFactory.getInstance(ContextUtils.getApplicationContext()))
            .get(UserViewModel::class.java)
        btnSendToB.setOnClickListener {
            //A向B发送数据
            mModel?.getAccount()?.postValue(AccountBean("FragmentA的消息:杨洛峋",5))
        }
        //当数据有变化的时候执行此方法
        mModel?.getAccount()?.observe(requireActivity()) {
            tvContentA.text = "接收到来自${it.name} ${it.age} 岁了!"
        }

    }

}

fragment_a.layout

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btnSendToB"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="A发送消息"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tvContentA"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=""
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

FragmentB.kt

/**
 * 使用LiveData+ViewModel让A和B进行通信
 */
class FragmentB : Fragment() {

    private var mModel: UserViewModel? = null
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_b, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        //第一种实现方式
//        mModel = ViewModelProvider(requireActivity()).get(UserViewModel::class.java)
        //第二种实现方式
        mModel = ViewModelProvider(requireActivity(),ViewModelProvider.AndroidViewModelFactory.getInstance(ContextUtils.getApplicationContext())).get(UserViewModel::class.java)
        btnSendToA.setOnClickListener {
            mModel?.getAccount()?.postValue(AccountBean("FragmentB的消息:杨洛峋小宝宝",5))
        }

        mModel?.getAccount()?.observe(requireActivity()){
            tvContentB.text = "接收到来自${it.name} ${it.age} 岁了!"
        }
    }
}

framgent_b.layout

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btnSendToA"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="B发送消息"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tvContentB"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=""
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

  运行测试结果:

              

 

标签:Fragment,mModel,ViewModel,ViewModelProvider,Activity,UserViewModel,class
From: https://www.cnblogs.com/tony-yang-flutter/p/17622690.html

相关文章

  • 简单介绍LiveData、ViewModel以及使用二者封装一个简单的基类用于测试
    一、概述1.LiveData概述什么事LiveData?1.LiveData是一种可观察的数据存储器类2.LiveData是一个数据持有者,给源数据包装一层。3.源数据使用LiveData包装后,可以被observer观察,数据有更新时observer可感知。4.但observer的感知,只发生在(Activity/Fragment......
  • ViewModel
    一.视图和数据模型之间的桥梁ViewModel在页面(Activity/Fragment)功能较为简单的情况下,通常会把UI交互,与数据获取等相关的业务逻辑全部写在页面中。但是在页面功能复杂的情况下,这样做是不合适的,因为它不符合“单一功能原则”。页面应该只负责处理用户和UI控件的交互,并将数据......
  • Android Activity的创建流程(Android-10)
    前言本篇笔记从最基础的startActivity(Intent)看一下Activity的启动流程。同时由于Launcher的启动后续和这里基本类似,就记录在一起。客户端发送请求startActivity发送启动请求的流程本质上就是:向ActivityManagerService发送启动请求。由于发送端基本是在当前用户App进程或者Launche......
  • Activity之间数据交流一(startActivityForResult , onActivityResult , setResult 的用
    主Activity)上能连接往许多不同子功能模块(子Activity上去),当子模块的事情做完之后就回到主界面,或许还同时返回一些子模块完成的数据交给主Activity处理。这样的数据交流就要用到主Activity回调函数onActivityResult()。一些方法: 主Activity中:<1>主Activity......
  • 关于3dtiles Interactivity中的zoom方法精简写法
    原版本涉及到坐标系变化和矩阵变换,在对原版的思路掌握后,特写一个精简版,帮助大家理解。functionzoom(movement,feature){constlongitude=Cesium.Math.toRadians(feature.getProperty("Longitude"));constlatitude=Cesium.Math.toRadians(feature.getProperty("Lati......
  • 拼多多APP商品详情接口获取activity_id值(拼多多activity_id接口)
    拼多多APP商品详情接口获取activity_id值(拼多多activity_id接口)代码对接如下:1.公共参数名称类型必须描述keyString是调用key(必须以GET方式拼接在URL中secretString是调用密钥api_nameString是API接口名称(包括在请求地址中)[item_search,item_get,item_search_shop等]cacheString否[......
  • android中使用startActivityForRes…
    网上找的一个通俗易懂,放在这以后好查阅假设:我这里有两个Activity:A和B,从A中向B中传递数据的时候采用的是Bundle封装数据,然后从A中跳转到B中,当B有需求将数据封装起来回传给A并跳转回A。那么A中接收数据时还要先判断Bundle是否为空,因为第一次访问A的时候(即B还没有回传的时候),Bundle......
  • Android Fragments 详细使用
    AndroidFragments详细使用 Fragments诞生初衷  自从Android3.0中引入fragments的概念,根据词海的翻译可以译为:碎片、片段。其上的是为了解决不同屏幕分辩率的动态和灵活UI设计。大屏幕如平板小屏幕如手机,平板电脑的设计使得其有更多的空间来放更多的UI组件,而多出......
  • android隐式启动Activity的例子
    android隐式启动Activity的例子【原创】android2.2测试通过android隐匿启动Activity的例子,同样适用于Service,BroadcastReceiver<activityandroid:name=".MyActivityTwo"android:label="ThisMyActivityTwo"><!--这样进行匹配:Intentintent=newIntent(Intent.ACT......
  • Activity及其生命周期
    Activity是Android用户界面的基础组件,它一般存放在任务栈(Task)中, 所以Activity是以栈的形式存放的,也就遵循先进后出的原则,也不支持重新排序。如果要改变Activtiy的顺序,只能根据压栈和出栈的操作来改变。当启动一个Application时,系统会默认创建一个对应的Task,用来存放......