Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/188.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android live data observer不支持';我不能一刀切地离开_Android_Fragment_Android Livedata_Flow - Fatal编程技术网

Android live data observer不支持';我不能一刀切地离开

Android live data observer不支持';我不能一刀切地离开,android,fragment,android-livedata,flow,Android,Fragment,Android Livedata,Flow,我刚刚使用android的新功能,如hilt、view model、coroutines flow等。我的应用程序中一直存在问题,当我更换碎片时,这些问题一直在发生,我注意到我的实时数据观察者没有被删除,我看到一些帖子和评论说,我必须在onViewCreated上设置我的观察者,并在onDestroyView上删除它们,我还必须使用viewLifecycleOwner实例,我尝试了所有观察者,我仍然看到相同的问题,有人能告诉我问题出在哪里吗?我的代码如下: 注意:如果没有用户交互,我每120秒调

我刚刚使用android的新功能,如hilt、view model、coroutines flow等。我的应用程序中一直存在问题,当我更换碎片时,这些问题一直在发生,我注意到我的实时数据观察者没有被删除,我看到一些帖子和评论说,我必须在onViewCreated上设置我的观察者,并在onDestroyView上删除它们,我还必须使用viewLifecycleOwner实例,我尝试了所有观察者,我仍然看到相同的问题,有人能告诉我问题出在哪里吗?我的代码如下:

注意:如果没有用户交互,我每120秒调用一次这个片段

**My BaseFragment**

@ExperimentalCoroutinesApi
@InternalCoroutinesApi
abstract class BaseFragment : Fragment() {

    abstract fun setUpFragment()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        setUpFragment()
    }

}

**//My fragment**

@ExperimentalCoroutinesApi
@InternalCoroutinesApi
@AndroidEntryPoint
class PinCodeFragment : BaseFragment() {

    companion object {
        fun newInstance() = PinCodeFragment()
    }


    private val viewModel by activityViewModels<PinCodeViewModel>()

    private var _binding: PinCodeFragmentBinding? = null
    private val binding: PinCodeFragmentBinding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = PinCodeFragmentBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun setUpFragment() {
        setupWatcher()
        setupObservables()
    }

    private fun setupWatcher() {
        binding.pingNumberEdt.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
            }

            override fun onTextChanged(s: CharSequence?, p1: Int, p2: Int, p3: Int) {
                if (s != null && s.length == 4) {
                    viewModel.sendPin(AuthenticateRequest(binding.pingNumberEdt.text.toString().sha256()))
                }
            }

            override fun afterTextChanged(p0: Editable?) {
            }
        })

    }

    private fun setupObservables() {
        viewModel.pinDodeData.observe(viewLifecycleOwner, Observer {
            when (it) {
                //Web service Result handler
            }
        })
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
        viewModel.pinDodeData.removeObservers(viewLifecycleOwner)
    }
}

**My ViewModel**
     
@ExperimentalCoroutinesApi
@InternalCoroutinesApi
class PinCodeViewModel @ViewModelInject constructor(private val repository: PinCodeRepository) :
    ViewModel() {

    private val _pinDodeData = MutableLiveData<Result<AuthenticateResponse>>()
    val pinDodeData: LiveData<Result<AuthenticateResponse>> = _pinDodeData

    fun sendPin(pin: AuthenticateRequest) {
        viewModelScope.launch {
            repository.sendPinCode(pin).onEach {
                _pinDodeData.postValue(it)
            }.launchIn(viewModelScope)
        }
    }
}

**My Repository**

class PinCodeRepository @Inject constructor(
    private val api: Api,
    private val preferences: DealerPreferences,
    private val gsn: Gson
) : IPinCodeRepository {

    override fun sendPinCode(request: AuthenticateRequest) = flow {
        try {
            emit(Result.Loading)

            val res = api.authenticate(Utils.generateHMAC(), request)

            val error = res.validate(gsn)
            if (error != null) {
                emit(Result.Error(error))
                return@flow
            }

            if (res.body() == null && res.code() == 200) {
                emit(Result.Error(Exception("Server error (empty response).")))
                return@flow
            }

            preferences.setStringPreference(DealerPreferences.PIN, request.pinHash)
            emit(Result.Success(res.body()as AuthenticateResponse))
        } catch (e: Exception) {
            emit(Result.Error(e))
        }
    }

}
**我的基本片段**
@实验常规
@内部协同程序API
抽象类BaseFragment:Fragment(){
抽象片段()
覆盖已创建的视图(视图:视图,保存状态:捆绑?){
super.onViewCreated(视图,savedInstanceState)
setUpFragment()
}
}
**//我的碎片**
@实验常规
@内部协同程序API
@雄蕊识别点
类PinCodeFragment:BaseFragment(){
伴星{
fun newInstance()=PinCodeFragment()
}
按activityViewModels()列出的私有val视图模型
私有变量绑定:PinCodeFragmentBinding?=null
私有val绑定:PinCodeFragmentBinding get()=\u绑定!!
覆盖创建视图(
充气机,
容器:视图组?,
savedInstanceState:捆绑?
):查看{
_绑定=PinCodeFragmentBinding.充气(充气器、容器、假)
返回binding.root
}
重写片段(){
setupWatcher()
可观测的
}
私人娱乐观察者(){
binding.pingNumberEdt.addTextChangedListener(对象:TextWatcher{
重写更改前的乐趣(p0:CharSequence?,p1:Int,p2:Int,p3:Int){
}
重写已更改的上下文(s:CharSequence?,p1:Int,p2:Int,p3:Int){
如果(s!=null&&s.length==4){
viewModel.sendPin(AuthenticateRequest(binding.pingNumberEdt.text.toString().sha256())
}
}
覆盖后文本更改(p0:可编辑?){
}
})
}
私人娱乐设置(可观察){
viewModel.pinDodeData.observe(viewLifecycleOwner,Observer{
什么时候{
//Web服务结果处理程序
}
})
}
重写onDestroyView(){
super.onDestroyView()
_binding=null
viewModel.pinDodeData.removeObservers(viewLifecycleOwner)
}
}
**我的视图模型**
@实验常规
@内部协同程序API
类PinCodeViewModel@ViewModelInject构造函数(专用val存储库:PinCodeRepository):
ViewModel(){
private val_pinDodeData=MutableLiveData()
val pinDodeData:LiveData=_pinDodeData
趣味发送pin(pin:AuthenticateRequest){
viewModelScope.launch{
repository.sendPinCode(pin).onEach{
_pinDodeData.postValue(it)
}.launchIn(viewModelScope)
}
}
}
**我的存储库**
类PinCodeRepository@Inject构造函数(
私有val api:api,
私有val首选项:DealerPreferences,
私人val gsn:Gson
):Ipincodepository{
覆盖fun sendPinCode(请求:AuthenticateRequest)=流{
试一试{
发射(结果加载)
val res=api.authenticate(Utils.generateHMAC(),请求)
val错误=res.validate(gsn)
if(错误!=null){
发出(结果错误(错误))
return@flow
}
if(res.body()==null&&res.code()==200){
emit(Result.Error(异常(“服务器错误(空响应))
return@flow
}
preferences.setStringPreference(DealerPreferences.PIN、request.pinHash)
emit(Result.Success(res.body()作为AuthenticateResponse))
}捕获(e:例外){
发射(结果错误(e))
}
}
}

“我注意到我的实时数据观察程序没有被删除”-您是如何验证这一点的,您能否提供这一证据。当我再次调用片段时,web服务处理程序在一开始就被调用,就像我调用web服务一样,但我没有调用它。(方法setupObservables()->//Web服务结果处理程序)因此,如果使用activityViewModels,则视图模型的生存期可能长于片段生命周期。关联的视图模型具有
活动的生命周期。就个人而言,为不同片段共享视图模型的想法是一种反模式。。我想你可能已经找到了一个原因。尝试改用视图模型{my factory}
使用
。当调用视图模型时,作为视图模型的
init{}
块中的测试注销。。如果你回头看,你认为是被破坏的片段,而init块没有被调用,你肯定是在使用同一个视图模型实例,但你是对的,我只是改变了创建我的视图模型的方式,我用的是activityViewModels(以前),我现在用的是viewModels(对于片段),我也看到了这个linnk:。