Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

遇到个bug #30

Closed
ysjava opened this issue Jun 22, 2021 · 9 comments
Closed

遇到个bug #30

ysjava opened this issue Jun 22, 2021 · 9 comments

Comments

@ysjava
Copy link

ysjava commented Jun 22, 2021

场景: 一个activity,监听viewmodel中的livedata,两个fragment,两个fragment中都有一个按钮,点击就会通过viewmodel切换显示。 发现各自点击两次后就不能响应点击事件了

@hi-dhl
Copy link
Owner

hi-dhl commented Jun 23, 2021

各自点击两次后就不能响应点击事件了??? 你是想说在 activity 监听的 livedata 无法接受到点击事件吧。

@hi-dhl
Copy link
Owner

hi-dhl commented Jun 23, 2021

activity 包含两个fragment ,需要共享 activity 的 ViewModel 的,才可以进行通信,这部分内容详见 Google 文档: https://developer.android.com/topic/libraries/architecture/viewmodel?hl=zh-cn#sharing

@ysjava ysjava closed this as completed Jun 23, 2021
@ysjava
Copy link
Author

ysjava commented Jun 23, 2021

各自点击两次后就不能响应点击事件了??? 你是想说在 activity 监听的 livedata 无法接受到点击事件吧。

我在按钮的点击监听中断点,每个按钮就前两次响应了点击,后面就没反应了,两个fragment都是共享的activity的viewmodel。 然后就是我测试了下官方的使用方式,发现可以正常响应

@ysjava ysjava reopened this Jun 23, 2021
@hi-dhl
Copy link
Owner

hi-dhl commented Jun 23, 2021

各自点击两次后就不能响应点击事件了??? 你是想说在 activity 监听的 livedata 无法接受到点击事件吧。

我在按钮的点击监听中断点,每个按钮就前两次响应了点击,后面就没反应了,两个fragment都是共享的activity的viewmodel。 然后就是我测试了下官方的使用方式,发现可以正常响应

方便贴一下 activity 和 fragment 点击相关的代码吗?

@ysjava
Copy link
Author

ysjava commented Jun 23, 2021

各自点击两次后就不能响应点击事件了??? 你是想说在 activity 监听的 livedata 无法接受到点击事件吧。

我在按钮的点击监听中断点,每个按钮就前两次响应了点击,后面就没反应了,两个fragment都是共享的activity的viewmodel。 然后就是我测试了下官方的使用方式,发现可以正常响应

方便贴一下 activity 和 fragment 点击相关的代码吗?

Activity

  • `class LoginActivity : AppCompatActivity() {
    //当前显示的fragment
    private lateinit var curFragment: Fragment
    private lateinit var pawLoginFragment: Fragment
    private lateinit var codeLoginFragment: Fragment
    private val viewModel by lazy { ViewModelProvider(this).get(LoginViewModel::class.java) }
    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_login)
    onObserve()
    codeLoginFragment = CodeLoginFragment()
    pawLoginFragment = PawLoginFragment()
    curFragment = codeLoginFragment

      supportFragmentManager
          .beginTransaction()
          .add(R.id.lay_container, curFragment)
          .commit()
    

    }

    private fun onObserve() {
    viewModel.skipLoginView.observe(this, {
    val fragment: Fragment =
    if (curFragment == codeLoginFragment)
    pawLoginFragment
    else
    codeLoginFragment

          curFragment = fragment
    
          supportFragmentManager
              .beginTransaction()
              .replace(R.id.lay_container, fragment)
              .commit()
      })
    

    }
    }`

ViewModel

  • `class LoginViewModel : ViewModel() {
    val skipLoginView = MutableLiveData()

    fun skipLoginView(string: String) {
    this.skipLoginView.value = string
    }
    }`

Fragment 1

  • `class CodeLoginFragment : Fragment() {
    private val viewModel by lazy { ViewModelProvider(activity!!).get(LoginViewModel::class.java) }

    private val binding: FragmentCodeLoginBinding by viewbind()
    override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
    ): View {
    return inflater.inflate(R.layout.fragment_code_login, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)

      binding.btnSkip.setOnClickListener {
          viewModel.skipLoginView("CODE")
      }
    

    }
    }`

Fragment 2

  • `class PawLoginFragment : Fragment() {
    private val binding: FragmentPawLoginBinding by viewbind()
    private val viewModel by lazy { ViewModelProvider(activity!!).get(LoginViewModel::class.java) }
    override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
    ): View {
    return inflater.inflate(R.layout.fragment_paw_login, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)

      binding.btnSkip.setOnClickListener {
          viewModel.skipLoginView("PAW")
      }
    

    }

}`

按钮

  • <Button android:text="SKIP" android:id="@+id/btn_skip" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />

@hi-dhl
Copy link
Owner

hi-dhl commented Jun 24, 2021

按照你的例子,我写了一个,我这边可以正常切换的, 以下写法 java 和 kotlin

ViewBindActivity.kt

class ViewBindActivity : AppCompatActivity() {
    val binding: ActivityViewBindBinding by viewbind()
    // java
    val loginViewModel: LoginViewModel by lazy { ViewModelProvider(this).get(LoginViewModel::class.java) }
  //  kotlin  
  // val loginViewModel: LoginViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding.apply {
            loginViewModel.liveData.observe(this@ViewBindActivity) {
                if (it.equals("login")) {
                    addFragment(LoginFragment())
                } else {
                    addFragment(ViewBindFragment())
                }
            }
            addFragment(ViewBindFragment())
        }
    }

    private fun addFragment(fragment: Fragment) {
        supportFragmentManager.beginTransaction()
            .replace(R.id.container, fragment)
            .commit()
    }
}

ViewBindFragment.kt

class ViewBindFragment : Fragment(R.layout.fragment_view_bind){
    
    // java
    private val loginViewModel by lazy { ViewModelProvider(requireActivity()).get(LoginViewModel::class.java) }
   // kotlin
   private val loginViewModel by activityViewModels()

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

        btnLogin.setOnClickListener{
            loginViewModel.liveData.value = "login"
        }

    }
}

LoginFragment.kt

class LoginFragment : Fragment(R.layout.fragment_login){
    
    // java
    private val loginViewModel by lazy { ViewModelProvider(requireActivity()).get(LoginViewModel::class.java) }
   // kotlin
   private val loginViewModel by activityViewModels()

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

        btnViewBind.setOnClickListener{
            loginViewModel.liveData.value = "viewBind"
        }

    }
}

@ysjava
Copy link
Author

ysjava commented Jun 24, 2021

loginViewModel.liveData.observe(this@ViewBindActivity) {
if (it.equals("login")) {
addFragment(LoginFragment())
} else {
addFragment(ViewBindFragment())
}
}

你这儿的addFragment(fragment)里面每次都是给的一个新的对象,不给新的对象就不行。

@hi-dhl
Copy link
Owner

hi-dhl commented Jun 24, 2021

问题【点击两次后就不能响应点击事件了】

这里,为了方便,我这是根据demo 里面的代码改的,只要能接受到消息,执行显示隐藏就可以了,我这里点击了很多次,都是正常的

@hi-dhl
Copy link
Owner

hi-dhl commented Jun 24, 2021

我看你的代码里面

  supportFragmentManager
      .beginTransaction()
      .replace(R.id.lay_container, fragment)
      .commit()

如果只是切换显示的话,不用调用 replease, 调用 show 和 hide 即可

@ysjava ysjava closed this as completed Jun 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants