我正在创建一个播客应用,其单个活动包含2个元素:
我想设置一个参照exoplayer视图的全局变量,因此我可以在片段和附加的viewmodel中使用此变量来播放/停止/加载音频。我如何在Kotlin中有效地实现这一点?
现在,每当我需要片段中的exoplayer时,我都会重新创建一个像这样的变量:
var exoplayerView = (activity as MainActivity).exoplayer_view
通过在活动中设置全局变量,我不必在整个应用程序中一次又一次地执行此操作。与在每个片段/视图模型中创建另一个引用相比,这可能还没有占用更多的内存。
MainActivity:
...
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
// global reference to use for all fragments, viewmodels and helper classes
var exoplayerView: PlayerControlView = exoplayer_view
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
....
}
override fun onStop() {
super.onStop()
releasePlayer(exoplayer_view)
}
}
片段:
class TracksFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
...
// make use of exoplayer reference within the fragment and/or viewmodel
// the exoplayerView variable can not be recognised here
if(exoplayerView.player==null) exoplayerView.player = viewModel.player
...
return binding.root
}
}
我认为,通过像这样设置exoplayerView参考,我可以从片段中获取它。但是事实并非如此。我该如何有效地做这样的事情?
答案 0 :(得分:1)
不应像那样“全局”访问视图,请尝试将“活动”和“片段”视为封闭的模块,其内部功能被隐藏并由面向公众的界面保护。
以下是在共享ViewModels成为事物之前推荐的一种方法:
https://developer.android.com/training/basics/fragments/communicating
基本上,您可以使Activity实现某种接口,该接口表示您希望子片段可以访问的功能。然后,片段通过将其具有的Activity实例强制转换为该接口类型的变量来访问此对象。这样,您就可以直接在Fragment中调用该方法。
更好的方法是在“活动”和“片段”之间使用共享的ViewModel。您可以使ViewModel公开这些活动和片段可以设置和观察的可观察字段或LiveData。例如,您可以在ViewModel中有一个表示该播放器状态的字段。片段中的某些用户操作可以设置该字段的值,活动中的观察者可以触发播放器中的某些行为。