android - Kotlin:不同片段之间的通信
问题描述
感谢 Kotlin,我目前正在开发一个 Android 应用程序。
我正在使用默认的导航抽屉和片段。我想做这样的事情:
- 在当前片段上,将一些数据放入微调器(完成)
- 单击文本视图时,保持数据(来自选定的微调器)处于选中状态(几乎完成),然后(3)
- 转到另一个片段(完成)
- 在这个片段上,创建一个带有一些数据的微调器并将它们发送到第一个片段(几乎完成)
- 插入新值和旧的第一个片段
所以我有两个微调器,第二个(在第二个片段上)有一个适配器。
我的问题是:有没有办法更容易做到这一点?我正在为片段和适配器之间的所有捆绑而苦苦挣扎,但我真的相信有一种比我正在做的更简单的方法......
第一个片段:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val v = inflater.inflate(R.layout.mes_informations, container, false)
val thisBundle = this.arguments
if(thisBundle != null){
val builder = StringBuilder("Extras:\n")
for (key in thisBundle.keySet()) {
val value = thisBundle.get(key)
builder.append(key).append(": ").append(value).append("\n")
}
selectedArret.text = thisBundle.get("Arret").toString()
}
return v
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val thisBundle = this.arguments
if(thisBundle != null){
val builder = StringBuilder("Extras:\n")
for (key in thisBundle.keySet()) {
val value = thisBundle.get(key)
builder.append(key).append(": ").append(value).append("\n")
}
Log.i(TAG, builder.toString())
}
bundle = Bundle()
spinnerDepartement.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
when (position) {
position -> departement = bundle.putString("departement", spinnerDepartement.selectedItem.toString())
else -> bundle.putString("departement", "Cher")
}
Log.i(TAG, spinnerDepartement.selectedItem.toString())
}
override fun onNothingSelected(parent: AdapterView<*>) {
}
}
val fragmentTransaction = fragmentManager?.beginTransaction()
val rechercheFragm = RechercherArret()
rechercheFragm.arguments = bundle
ligneReguliereLayout.setOnClickListener {
fragmentTransaction
?.replace(R.id.content_frame, rechercheFragm)
?.addToBackStack(null)
?.commit()
}
}
第二 :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
lignes = ArrayList()
val resultArgument = arguments
val queryFill = resources.getStringArray(R.array.fillSearchQuery2)
for(ligne in queryFill){
lignes.add(ligne)
}
adapter = ListAdapterCustom(view.context, R.layout.list_adapter, lignes, resultArgument)
listSearchView.adapter = adapter
search.queryHint = "Entrez un arrêt"
search.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextChange(newText: String): Boolean {
adapter.filter.filter(newText.trim())
if(newText.trim() != ""){
listSearchView.visibility = View.VISIBLE
}else{
listSearchView.visibility = View.GONE
}
return false
}
override fun onQueryTextSubmit(query: String): Boolean {
Toast.makeText(view.context, "Submit $query", Toast.LENGTH_SHORT).show()
return false
}
})
}
和适配器:
class ListAdapterCustom(context: Context, resource: Int, list: ArrayList<String>, private val arguments: Bundle?) : ArrayAdapter<String>(context, resource, list) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = super.getView(position, convertView, parent)
val thisBundle = arguments
if(thisBundle != null){
val builder = StringBuilder("Extras:\n")
for (key in thisBundle.keySet()) {
val value = thisBundle.get(key)
builder.append(key).append(": ").append(value).append("\n")
}
Log.i("Extras", builder.toString())
}
val arret = view.findViewById<TextView>(R.id.arret)
arret.setOnClickListener {
val fragment = MesInformations()
val bundle = Bundle()
bundle.putString("Arret", arret.text.toString())
fragment.arguments = bundle
Snackbar.make(view, arret.text, Snackbar.LENGTH_SHORT).show()
val fragmentManager = (context as AppCompatActivity).supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
fragmentTransaction.replace(R.id.content_frame, fragment).addToBackStack(null)
fragmentTransaction.commit()
fragmentTransaction.addToBackStack(null)
}
if (position % 2 == 1) {
view.setBackgroundResource(R.color.colorWhite)
} else {
view.setBackgroundResource(R.color.grayBackground)
}
return view
}
}
解决方案
您可以创建共享ViewModel
以在片段之间进行通信。创建一个ViewModel
并使用Activity
每个片段内的主机上下文访问它们。
这是从此处的 ViewModel 文档复制的示例: https ://developer.android.com/topic/libraries/architecture/viewmodel
class SharedViewModel : ViewModel() {
val selected = MutableLiveData<Item>()
fun select(item: Item) {
selected.value = item
}
}
class MasterFragment : Fragment() {
private lateinit var itemSelector: Selector
private lateinit var model: SharedViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
model = activity?.run {
ViewModelProviders.of(this).get(SharedViewModel::class.java)
} ?: throw Exception("Invalid Activity")
itemSelector.setOnClickListener { item ->
model.select(item) // <-- This will notify the `DetailFragment`
}
}
}
class DetailFragment : Fragment() {
private lateinit var model: SharedViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
model = activity?.run {
ViewModelProviders.of(this).get(SharedViewModel::class.java)
} ?: throw Exception("Invalid Activity")
model.selected.observe(this, Observer<Item> { item ->
// Update the UI
})
}
}
在这里, 和都SharedViewModel
可以访问。两者都在访问同一个实例,因为他们都从的 Context 访问 ViewModel:MasterFragment
DetailFragment
SharedViewModel
Activity
ViewModelProviders.of(*ACTIVITY*).get(SharedViewModel::class.java)
现在您可以在 中包含一些LiveData
,SharedViewModel
并且两个片段都可以侦听/更新它们,这最终也会反映在另一个片段上。
推荐阅读
- awk - 这个功能是什么意思?功能 $$1
- python-3.x - 如何检测文本文件中已保存的链接
- angular - 我想使用带有冲突选择器的 3rd 方库
- android - 应用程序在某些模拟器上启动时崩溃 - 为什么?
- spring-boot - 如果存在春豆,我如何检查 Thymeleaf
- batch-file - 如何通过密码锁定文件夹而不回显?
- java - 如何在警报对话框中添加复选框?
- django - Django告诉我桌子是空的
- amazon-web-services - 无法删除存储桶中的所有对象,存储桶不会被删除 AWS S3
- php - php Symfony 3 将动态实体管理器传递给请求侦听器