I have managed to switch between fragment, but the changes on current fragment doesn't applied when entering a new fragment. I have 2 fragments, HomeFragment
and Subreddit
. When I first run the app, it shows HomeFragment
which is showing r/aww
content. If I click action bar, it will change into Subreddit fragment. In Subreddit
fragment, I can click a subreddit category (e.g. r/sports
, r/news
, etc.). After I click a subreddit category, the fragment change to HomeFragment
again where it should shows the content of subreddit category I just choose, but it doesn't. I choose r/news
while in Subreddit
fragment, but it still showing the first subreddit category when I run my app, which is r/aww
.
Here is my MainActivity.kt
class MainActivity : AppCompatActivity() {
companion object {
var globalDebug = false
lateinit var jsonAww100: String
lateinit var subreddit1: String
private const val mainFragTag = "mainFragTag"
private const val favoritesFragTag = "favoritesFragTag"
private const val subredditsFragTag = "subredditsFragTag"
}
private var actionBarBinding: ActionBarBinding? = null
private val viewModel: MainViewModel by viewModels()
fun hideKeyboard() {
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(window.decorView.rootView.windowToken, 0)
}
private fun initActionBar(actionBar: ActionBar) {
actionBar.setDisplayShowTitleEnabled(false)
actionBar.setDisplayShowCustomEnabled(true)
actionBarBinding = ActionBarBinding.inflate(layoutInflater)
actionBar.customView = actionBarBinding?.root
}
private fun actionBarTitleLaunchSubreddit() {
actionBarBinding?.actionTitle?.setOnClickListener {
actionBarBinding?.actionTitle?.text = "Pick"
supportFragmentManager.commit {
add(R.id.main_frame, Subreddits.newInstance(), subredditsFragTag)
setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
}
}
}
private fun addHomeFragment() {
supportFragmentManager.commit {
add(R.id.main_frame, HomeFragment.newInstance(), mainFragTag)
setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
}
}
private fun initDebug() {
if(globalDebug) {
assets.list("")?.forEach {
Log.d(javaClass.simpleName, "Asset file: $it" )
}
jsonAww100 = assets.open("aww.hot.1.100.json.transformed.txt").bufferedReader().use {
it.readText()
}
subreddit1 = assets.open("subreddits.1.json.txt").bufferedReader().use {
it.readText()
}
}
}
private fun initTitleObservers() {
viewModel.observeTitle().observe(this){
actionBarBinding?.actionTitle?.text = it
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
setSupportActionBar(activityMainBinding.toolbar)
supportActionBar?.let{
initActionBar(it)
}
addMenuProvider(object : MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.menu_main, menu)
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
return when (menuItem.itemId) {
android.R.id.home -> false
else -> true
}
}
})
addHomeFragment()
initDebug()
initTitleObservers()
actionBarTitleLaunchSubreddit()
actionBarLaunchFavorites()
actionBarSearch()
viewModel.setTitleToSubreddit()
}
}
Here is my MainViewModel.kt
class MainViewModel : ViewModel() {
private var title = MutableLiveData<String>()
private var api = RedditApi.create()
private var repository = RedditPostRepository(api)
private val data = MutableLiveData<List<RedditPost>>()
private val subred = MutableLiveData<List<RedditPost>>()
private var subreddit = "aww"
fun netFetchData() = viewModelScope.launch(
context = viewModelScope.coroutineContext
Dispatchers.IO) {
data.postValue(repository.getPosts(subreddit.value.toString()))
}
fun observeData(): LiveData<List<RedditPost>> {
return data
}
fun updateNewCategory(updateTitle: String){
subreddit = updateTitle
}
fun observeNewCategory(): String {
return subreddit
}
fun netFetchSubreddit() = viewModelScope.launch(
context = viewModelScope.coroutineContext
Dispatchers.IO) {
subred.postValue(repository.getSubreddits())
}
fun observeSubreddit(): LiveData<List<RedditPost>> {
return subred
}
fun setTitleToSubreddit() {
title.value = "r/${subreddit.value}"
}
fun observeTitle(): LiveData<String> {
return title
}
fun setTitle(newTitle: String) {
title.value = newTitle
}
}
Here is my SubredditListAdapter.kt
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
val binding = RowSubredditBinding.inflate(LayoutInflater.from(parent.context),
parent, false)
val holder = VH(binding)
holder.rowSubredditBinding.root.setOnClickListener {
viewModel.setTitle(getItem(holder.adapterPosition).displayName.toString())
viewModel.updateNewCategory(getItem(holder.adapterPosition).displayName.toString())
fragmentActivity.supportFragmentManager.commit{
add(R.id.main_frame, HomeFragment.newInstance(), "mainFragTag")
setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
}
}
return holder
}
Here is my HomeFragment.kt
:
class HomeFragment: Fragment() {
private val viewModel: MainViewModel by viewModels()
private var _binding: FragmentRvBinding? = null
private val binding get() = _binding!!
companion object {
fun newInstance(): HomeFragment {
return HomeFragment()
}
}
private fun initAdapter(binding: FragmentRvBinding) : PostRowAdapter {
val rv = binding.recyclerView
val adapter = PostRowAdapter(viewModel)
rv.adapter = adapter
rv.layoutManager = LinearLayoutManager(binding.root.context)
viewModel.netFetchData(viewModel.observeNewCategory())
viewModel.observeData().observe(viewLifecycleOwner) {
adapter.submitList(it)
}
return adapter
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentRvBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Log.d(javaClass.simpleName, "onViewCreated")
initAdapter(binding)
}
}
I thought by using updateNewCategory
and observeNewCategory
would change the subreddit category, but turns out it didn't. How to update the category and apply the changes?
CodePudding user response:
What I am understanding with your code snippet is that your are trying to use common MainViewModel to communicate among your fragments and Activity.
Your issue is that you are creating new instance of MainViewModel in your fragment by using private val viewModel: MainViewModel by viewModels()
instead of using activityViewModel
Use following line to get viewModel reference of your activity in your fragment
private val viewModel: MainViewModel by activityViewModels()