首页 > 解决方案 > 具有两个片段的视图模型不起作用

问题描述

我正在开发一个应用程序,用户可以在他们的个人资料中添加他们的地址,现在我想在我从个人资料片段接收到的坐标上添加一个 viewModel 观察者,比如我的片段 A 并将此信息提供给地图片段,所以我可以在该位置创建一个新标记。显然我没有在我的片段 B 中获得观察者的任何信息。这就是我的代码:

这是配置文件的第一个片段:

class ProfilFoto : Fragment() {

    lateinit var mDatabase : DatabaseReference
    var mAuth = FirebaseAuth.getInstance()
    var user = FirebaseAuth.getInstance().currentUser
    var DISPLAY_NAME : String? = null
    private var model: Communicator?=null


    @SuppressLint("SetTextI18n", "ResourceType")
    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View? {
        //  setContentView(R.layout.fragment_notifications)
        val rootView: View = inflater.inflate(R.layout.fragment_profil_foto, container, false)


        model= activity?.let { ViewModelProviders.of(it).get(Communicator::class.java) }
        
        val loca = rootView.findViewById<View>(R.id.locationtext) as TextView
       
 var uid = user!!.uid

        val userHashMap = HashMap<String, Any>()

        mDatabase = FirebaseDatabase.getInstance().getReference("User").child(uid)

        val speicherButton = rootView.findViewById<Button>(R.id.speichern)



        speicherButton.setOnClickListener {

    
            val location = rootView.findViewById<View>(R.id.locationPerson) as EditText
            

            
            val loc = location.text.toString()
            if (!loc.isEmpty()) {

                Log.e("Location", loc)



                val locationAddress = GeocodingLocation()
                locationAddress.getAddressFromLocation(loc,
                        getActivity()?.getApplicationContext(), GeocoderHandler())

                model!!.setMsgCommunicator(locationAddress.toString())

                //userHashMap["Adresse"] = loc
                mDatabase.child("Adresse").setValue(loc)
                        .addOnSuccessListener {
                            Log.e("Telefon", loc)
                        }
                        .addOnFailureListener {
                            Log.e("Telefon2", "failed")
                        }

                //  mDatabase.updateChildren(userHashMap)
            }

            

    }

mDatabase.addValueEventListener(object : ValueEventListener {
            override fun onCancelled(error: DatabaseError) {
                TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
            }
return rootView
}

private class GeocoderHandler : Handler() {

        override fun handleMessage(message: Message) {

            val locationAddress: String?
            locationAddress = when (message.what) {
                1 -> {
                    val bundle: Bundle = message.getData()
                    bundle.getString("address")
                }
                else -> null
            }
            if (locationAddress != null) {
                Log.e("Handler", locationAddress)
            }
        }
    }

}

这是应该出现消息的地图片段:

class MapsFragment : Fragment() {

private val callback = OnMapReadyCallback { googleMap ->

 val model= activity?.let { ViewModelProviders.of(it).get(Communicator::class.java) }

        if (model != null) {
            model.message.observe(this, { t ->
                //txt.text = o!!.toString()
                Log.e("Marker", t.toString())
                var latlong = t.toString().split(",")
                var lat = parseFloat(latlong[0])
                var long = parseFloat(latlong[1])

                googleMap.addMarker(
                    MarkerOptions()
                        .position(LatLng(lat.toDouble(), long.toDouble()))
                        .title("Der Neue")
                )
            })
        }

}

override fun onCreateView(
           inflater: LayoutInflater,
           container: ViewGroup?,
           savedInstanceState: Bundle?
   ): View? {

 val rootView : View = inflater.inflate(R.layout.fragment_maps, container, false)

...

  return rootView
   }

这是我正在使用的通信器类:

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class Communicator : ViewModel(){

    val message =MutableLiveData<Any>()

    fun setMsgCommunicator(msg:String){
        message.setValue(msg)
    }
}

也许重要的是还显示我从中获取坐标的 GeoLocator:

private const val TAG = "GeocodingLocation"



public class GeocodingLocation  {
    lateinit var mDatabase : DatabaseReference
    var user = FirebaseAuth.getInstance().currentUser


    fun getAddressFromLocation(locationAddress: String,
                               context: Context?, handler: Handler?) {
        val thread: Thread = object : Thread() {
            override fun run() {

                val geocoder = Geocoder(context, Locale.getDefault())
                var result: String? = null
                var uid = user!!.uid
                
                mDatabase = FirebaseDatabase.getInstance().getReference("User").child(uid)
                try {

                    val addressList: List<*>? = geocoder.getFromLocationName(locationAddress, 1)
                    if (addressList != null && addressList.size > 0) {
                        val address: Address = addressList[0] as Address
                        val sb = StringBuilder()
                        sb.append(address.getLatitude()).append("\n")

                        mDatabase.child("Latitude").setValue(address.latitude)
                                .addOnSuccessListener {
                                    Log.e("Telefon", address.latitude.toString())
                                }
                                .addOnFailureListener {
                                    Log.e("Telefon2", "failed")
                                }
                       
                           
                        sb.append(address.getLongitude()).append("\n")

                        mDatabase.child("Longtitude").setValue(address.longitude)
                                .addOnSuccessListener {
                                    Log.e("Telefon", address.longitude.toString())
                                }
                                .addOnFailureListener {
                                    Log.e("Telefon2", "failed")
                                }

                        result = sb.toString()
                    }
                } catch (e: IOException) {
                    Log.e(TAG, "Unable to connect to Geocoder", e)
                } finally {
                    val message: Message = Message.obtain()
                    message.setTarget(handler)
                    if (result != null) {
                        message.what = 1
                        val bundle = Bundle()
                        bundle.putString("address", result)
                        message.setData(bundle)
                    } else {
                        message.what = 1
                        val bundle = Bundle()
                        result = """Address: $locationAddress
 Unable to get Latitude and Longitude for this address location."""
                        bundle.putString("address", result)
                        message.setData(bundle)
                    }
                    message.sendToTarget()
                }

            }
        }
        thread.start()
    }




}

有人知道我做错了什么而一无所获吗?就像在配置文件片段中一样,我在日志中收到纬度和经度。

标签: androidkotlinandroid-viewmodel

解决方案


将注册的观察者代码移到回调块之外。在回调内部,设置地图准备更新时的值。在观察者检查地图是否准备好,设置标记。希望有效!

private lateinit var googleMap: GoogleMap

private val callback = OnMapReadyCallback { map ->
    googleMap = map
}

val model= activity?.let { ViewModelProviders.of(it).get(Communicator::class.java) }

        

override fun onCreateView(
           inflater: LayoutInflater,
           container: ViewGroup?,
           savedInstanceState: Bundle?
   ): View? {

 val rootView : View = inflater.inflate(R.layout.fragment_maps, container, false)

    if (model != null) {
            model.message.observe(this, { t ->
                //txt.text = o!!.toString()
                Log.e("Marker", t.toString())
                var latlong = t.toString().split(",")
                var lat = parseFloat(latlong[0])
                var long = parseFloat(latlong[1])

                googleMap?.let{
                   it.addMarker(
                    MarkerOptions()
                        .position(LatLng(lat.toDouble(), long.toDouble()))
                        .title("Der Neue")
                )
            })
       }
  }

  return rootView
   }


推荐阅读