web-dev-qa-db-ja.com

ViewModelにLifecycleOwnerを含める必要がありますか?

LifecycleOwnerは、オブザーバーを作成するために現在必要です。

ViewModelにオブザーバーを作成するコードがあるので、フラグメントでViewModelを取得するときにLifecycleOwnerをアタッチします。

Googleのドキュメントによると。

注意:ViewModelは、ビュー、ライフサイクル、またはアクティビティコンテキストへの参照を保持する可能性のあるクラスを参照してはなりません。

私はその警告を破りましたか、もしそうなら、データを返すためにオブザーバーの作成を移動することをどのように勧めますか?

私はオブザーバーを作っただけなので、それがまだ有効かどうか疑問に思っています。また、Googleのドキュメントにも記載されています。

ViewModelオブジェクトには、LiveDataオブジェクトなどのLifecycleObserversを含めることができます。

MainFragment

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
}

MainViewModel

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
}
15
Hiroga Katageri

いいえ。ViewModel内の一部のLiveDataの変更を監視したい場合は、LifecicleOwnerを必要としないobserveForever()を使用できます。 ViewModels 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()
}

LiveDataを観察 の例を使用した非常に優れたリファレンス。

11
Vitaliy A

仮定:

  1. FuelViewModelを指します
  2. Fuel.request(IpAddressApi.MyIp())ViewModelのメソッドです
  3. IpAddressApi.MyIp()にはLifecycleOwnerへの参照がありません。

すべてが真の場合、違反していません。 LifecycleOwnerへのViewModel参照を渡していない限り、安全です!

LifecycleOwner-さまざまなAndroidライフサイクル、たとえばonCreate、onPause、onDestroyなどを所有しているため、アクティビティまたはフラグメントに関連しています

1
martinomburajr