代码之家  ›  专栏  ›  技术社区  ›  Hiroga Katageri

我应该在ViewModel中包含LifecycleOwner吗?

  •  43
  • Hiroga Katageri  · 技术社区  · 7 年前

    目前需要LifecycleOwner,以便创建观察者。

    我有在ViewModel中创建观察者的代码,所以在片段中检索ViewModel时,我附加LifecycleOwner。

    根据谷歌的文件。

    警告:ViewModel绝不能引用视图、生命周期或任何可能包含对活动上下文引用的类。

    我打破了那个警告了吗?如果我打破了,你建议我用什么方法来移动我创建的用于数据返回的观察者?

    我只是做了一个观察者,所以我想知道它是否仍然有效。因为谷歌的文档中也提到了这一点。

    ViewModel对象可以包含LifecycleObserver,例如LiveData对象。

    主要片段

    private lateinit var model: MainViewModel
    
    /**
     * Observer for our ViewModel IpAddress LiveData value.
     * @see Observer.onChanged
     * */
    private val ipObserver = Observer<String> {
        textIp.text = it
        hideProgressBar()
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        model = ViewModelProviders.of(this).get(MainViewModel::class.java)
        model.attach(this)
    }
    
    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? =
            inflater?.inflate(R.layout.fragment_main, container, false)
    
    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
    
        buttonRetrieveIp.setOnClickListener {
            showProgressBar()
            model.fetchMyIp().observe(this, ipObserver) //Here we attach our ipObserver
        }
    }
    
    override fun showProgressBar() {
    
        textIp.visibility = View.GONE
        progressBar.visibility = View.VISIBLE
    }
    
    override fun hideProgressBar() {
    
        progressBar.visibility = View.GONE
        textIp.visibility = View.VISIBLE
    }
    

    主视图模型

    private var ipAddress = MutableLiveData<String>()
    private lateinit var owner: LifecycleOwner
    
    fun attach(fragment: MainFragment) {
        owner = fragment
    }
    
    /**
     * For more information regarding Fuel Request using Fuel Routing and Live Data Response.
     * @see <a href="https://github.com/kittinunf/Fuel#routing-support">Fuel Routing Support</a>
     * @see <a href="https://github.com/kittinunf/Fuel#livedata-support">Fuel LiveData Support</a>
     * */
    fun fetchMyIp(): LiveData<String> {
    
        Fuel.request(IpAddressApi.MyIp())
                .liveDataResponse()
                .observe(owner, Observer {
    
                    if (it?.first?.statusCode == 200) {//If you want you can add a status code checker here.
    
                        it.second.success {
    
                            ipAddress.value = Ip.toIp(String(it))?.ip
                        }
                    }
                })
        return ipAddress
    }
    

    更新1:由于@pskink建议使用转换,改进了ViewModel。

    private lateinit var ipAddress:LiveData<String>
    
    /**
     * Improved ViewModel since January 23, 2018 credits to <a href="https://stackoverflow.com/users/2252830/pskink">pskink</a> <a href="
     *
     * For more information regarding Fuel Request using Fuel Routing and Live Data Response.
     * @see <a href="https://github.com/kittinunf/Fuel#routing-support">Fuel Routing Support</a>
     * @see <a href="https://github.com/kittinunf/Fuel#livedata-support">Fuel LiveData Support</a>
     * */
    fun fetchMyIp(): LiveData<String> {
    
        ipAddress = Transformations.map(Fuel.request(IpAddressApi.MyIp()).liveDataResponse(), {
    
            var ip:String? = ""
    
                it.second.success {
    
                    ip = Ip.toIp(String(it))?.ip
                }
            ip
        })
    
        return ipAddress
    }
    
    3 回复  |  直到 7 年前
        1
  •  60
  •   codingjeremy    4 年前

    否。如果您希望观察某些 LiveData 在您的 ViewModel 您可以使用 observeForever() 这不需要 LifecycleOwner .

    记住在上删除此观察者 视图模型 onCleared() 事件:

    val observer = new Observer() {
      override public void onChanged(Integer integer) {
        //Do something with "integer"
      }
    }
    

    ...

    liveData.observeForever(observer);
    

    ...

    override fun onCleared() {
        liveData.removeObserver(observer) 
        super.onCleared()
    }
    

    非常好的参考示例 observe LiveData .

        2
  •  2
  •   martinomburajr    7 年前

    假设:

    1. Fuel 指您的 ViewModel
    2. Fuel.request(IpAddressApi.MyIp()) 是您的 视图模型
    3. IpAddressApi.MyIp() 没有引用您的 LifecycleOwner ,

    如果一切都是真的,那么你没有违反它。只要你没有通过 生命周期所有者 参考 视图模型 你很安全!

    生命周期所有者 - 与活动或片段相关,因为它拥有各种Android生命周期,例如onCreate、onPause、onDestroy等

        3
  •  0
  •   Choletski    3 年前

    在里面 科特林 这可能类似于:

    val mObserver = Observer<List<QueueTabData>> { myString->
    // do something with myString
    }