having a problem with Navigation Advanced Sample provided by Google developers.
Main problem is that in regular case senario for Hilt dependency injection we can simply:
Create Custom FragmentFactory
Create Custom NavHostFragment
Asigne it to FragmentContainerView by using android:name="com.package.CustomNavHostFragment"
But how I can do it by using this Navigation Advanced Sample ?
Because now on Activity recreate I'm getting typical HILT error at package.MainActivity.onCreate(MainActivity.kt:23)
EDIT:
More about the problem. By this provided simple we should use
NavigationExtension.kt and setup everything by using BottomNavigationView.setupWithNavController
And problem is that we need to use the default NavHostFragment in order to create a container for each navigation graph.
Is it possible somehow to use custom NavHostFragment? If yes, how can I overite that NavHostFragment.onCreate() mechanism?
I'm talking about this line in NavigationExtension.kt class
If I understood your problem correctly, you want to create a custom NavHostFragment? Yes, that is possible but you don't need to overwrite NavHostFragment.onCreate(). Create a custom NavHostFragment with the following steps: First, create a MainFragmentFactory
MainFragmentFactory
class MainFragmentFactory #Inject constructor(
//... your dependencies
) : FragmentFactory() {
override fun instantiate(classLoader: ClassLoader, className: String): Fragment = when(className) {
MyFragment::class.java.name -> MyFragment(//.. your dependencies)
MySecondFragment::class.java.name -> MySecondFragment(/...)
// other fragments
else -> super.instantiate(classLoader, className)
}
}
Then you need to attach your fragmentFractory to your custom MainNavHostFragment
MainNavHostFragment
#AndroidEntryPoint
class MainNavHostFragment : NavHostFragment() {
#Inject
lateinit var mainFragmentFactory: MainFragmentFactory
override fun onAttach(context: Context) {
super.onAttach(context)
childFragmentManager.fragmentFactory = mainFragmentFactory
}
}
Now you need to add your custom NavHostFragment to your activity_main.xml
Activity_main.xml
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".framework.ui.view.MainActivity">
<fragment
android:id="#+id/fragment_container"
<!-- Add path to your custom NavHostFragment here -->
android:name="com.example.app.framework.ui.view.utils.MainNavHostFragment"
android:layout_width="match_parent"
android:layout_height="#dimen/wrapContent"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="#+id/bottomNavigationView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
<!-- Your NavGraph -->
app:navGraph="#navigation/nav_main" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigationView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:itemHorizontalTranslationEnabled="false"
app:labelVisibilityMode="labeled"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="#menu/bottom_nav_menu_logged_out" />
</androidx.constraintlayout.widget.ConstraintLayout>
Dagger-Hilt will now create all your fragments and instantiate it.
Related
I'm a beginner in MVVM and I tried this tutorial. Created a lot of files and pasted the codes but my views aren't recognized. My QuotesActivity.kt file:
package my.mvvm.ui.quotes
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import my.mvvm.R
import my.mvvm.data.Quote
import my.mvvm.utilities.InjectorUtils
class QuotesActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_quotes)
initializeUi()
}
private fun initializeUi() {
// Get the QuotesViewModelFactory with all of it's dependencies constructed
val factory = InjectorUtils.provideQuotesViewModelFactory()
// Use ViewModelProviders class to create / get already created QuotesViewModel
// for this view (activity)
val viewModel = ViewModelProviders.of(this, factory)
.get(QuotesViewModel::class.java)
// Observing LiveData from the QuotesViewModel which in turn observes
// LiveData from the repository, which observes LiveData from the DAO ☺
viewModel.getQuotes().observe(this, Observer { quotes ->
val stringBuilder = StringBuilder()
quotes.forEach { quote ->
stringBuilder.append("$quote\n\n")
}
textView_quotes.text = stringBuilder.toString()
})
// When button is clicked, instantiate a Quote and add it to DB through the ViewModel
button_add_quote.setOnClickListener {
val quote = Quote(editText_quote.text.toString(), editText_author.text.toString())
viewModel.addQuote(quote)
editText_quote.setText("")
binding.editText_author.setText("")
}
}
}
Any ideas why this happens? Already tried with two examples and I had the same issue. Thanks.
Edit:
import com.resocoder.mvvmbasicstut.data.Quote
import com.resocoder.mvvmbasicstut.databinding.ActivityQuotesBinding
import com.resocoder.mvvmbasicstut.utilities.InjectorUtils
//import kotlinx.android.synthetic.main.activity_quotes.*
class QuotesActivity : AppCompatActivity() {
lateinit var binding: ActivityQuotesBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityQuotesBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.quotes.QuotesActivity">
<TextView
android:id="#+id/textView_quotes"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintHeight_percent="0.55"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:scrollbars="vertical"
android:textAppearance="#style/TextAppearance.AppCompat.Large"
tools:text="I like pineapples. - Thomas Jefferson"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<EditText
android:id="#+id/editText_quote"
android:layout_width="0dp"
app:layout_constraintWidth_percent="0.7"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:hint="Quote"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView_quotes"
app:layout_constraintVertical_bias="0.0" />
<EditText
android:id="#+id/editText_author"
android:layout_width="0dp"
app:layout_constraintWidth_percent="0.7"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:hint="Author"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/editText_quote"
app:layout_constraintVertical_bias="0.0" />
<Button
android:id="#+id/button_add_quote"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:backgroundTint="?colorAccent"
android:text="Add Quote"
android:textColor="#android:color/white"
app:layout_constraintBottom_toBottomOf="#+id/editText_author"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toEndOf="#+id/editText_quote"
app:layout_constraintTop_toTopOf="#+id/editText_quote"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintWidth_percent="0.25" />
</androidx.constraintlayout.widget.ConstraintLayout>
I just edit project from github. You can find it here
The answer to 'Look at my edited question' in Laba Diena's 'Edit:' above of wanting to use View Binding instead of the Kotlin Android Extension with synthetic view bindings is fairly straight forward. There are only two project files that need changing, namely:
(1) 'build.gradle (Module)' and
(2) 'QuotesActivity.kt'
Note: The other project files from the MVVM tutorial can be used 'as is'.
Just make sure that your own 'package name' is at the top of these files.
Project Structure:
(1) build.gradle file:
a) Make this change to the 'plugins' section:
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-android-extensions' // Delete this line
}
b) Add this entry to the 'android' section:
android {
...
buildFeatures {
viewBinding true
}
}
c) Add this lifecycle option to the 'dependencies' section:
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
(2) QuotesActivity.kt:
Make the necessary changes to the 'QuotesActivity.kt' file as outlined below:
IMPORTANT: When this project is built, it generates a Java file with the necessary databindings for this activity file. It will contain new names that you will have to use with the 'binding' variable in place of the xml attribute names that were previously used. For example, 'button_add_quote' now becomes 'buttonAddQuote', etc. See excerpt below showing the other new names:
public final Button buttonAddQuote; // button_add_quote
public final EditText editTextAuthor; // editText_author
public final EditText editTextQuote; // editText_quote
public final TextView textViewQuotes; // textView_quotes
All these new names can be found in a file called 'ActivityQuotesBinding.java' which is located in the project folder:
'app/build/generated/data_binding_base_class_source_out/debug/out/com/example/mvvmcrashcourse/databinding/'
In the above path, the package name used for this particular project is "com.example.mvvmcrashcourse". Substitute it with your package name.
Finally, this solution works and was tested with Android Studio Bumblebee. If you have problems with build errors, try the following menu options:
Build -> Clean Project
Build -> Rebuild Project
File -> Invalidate Caches
My project contains multiple modules, and I am using aar files of other modules contains custom views and components. so I have an XML in .aar and I want to use it in my project.
Of course, I can but DataBinding doesn't generate it in the generated file, so I don't have access to XML's components and widgets.
My fragment's XML is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- Comes from AAR file -->
<include
android:id="#+id/toolbarLayout"
layout="#layout/simple_tool_bar" />
Simple toolbar is:
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="#dimen/simple_tool_bar_height"
app:elevation="0dp">
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/tool_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:navigationIcon="?attr/homeAsUpIndicator"
app:navigationIconTint="#color/primary" />
</com.google.android.material.appbar.AppBarLayout>
And Databinding generated file is:
public abstract class FragmentTestBinding extends ViewDataBinding {
#NonNull
public final View toolbarLayout;
So as you can see in the generated file toolbarLayout is an instance of View but it should be SimpleToolBarBinding.
When you are working on a project that contains modules instead of .aar it everything is working well, but after generating the .aar file and use it in another project it doesn't.
Conclude:
The Android Gradle Plugin (version: 7.2.0) doesn't support to generate the matched type of XxxBinding when the layout file is in class (aar).
Reason:
I compared the gradle tasks of using module's layout file with using aar's layout file.
We missed following gradle tasks:
:module:dataBindingMergeDependencyArtifactsDebug
:module:dataBindingMergeGenClassesDebug
:module:dataBindingGenBaseClassesDebug
And analyzed the related ViewBinding AGP source code, in the function of android.databinding.tool.writer.ViewBinderKt#toViewBinder
// Check to make sure that the ID matches a binding. Ignored tags like <merge> or <fragment>
// might have an ID but not have an actual binding. Only use ID if a match was found.
val rootBinding = bindings.singleOrNull { it.id == id }
if (rootBinding != null) {
return RootNode.Binding(rootBinding)
}
If the binding doesn't in the binding list, it would be regarded as View.
Workaround
Using the function of ViewBinding.bind(view: View) to inflate the XxxBinding manually.
layout file
<!-- activity_awesome.xml -->
<androidx.constraintlayout.widget.ConstraintLayout>
<include android:id="#+id/includes" layout="#layout/included_buttons" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- included_buttons.xml 在aar中-->
<androidx.constraintlayout.widget.ConstraintLayout>
<Button android:id="#+id/include_me" />
</androidx.constraintlayout.widget.ConstraintLayout>
Generated Code
// Activity.kt
class Activity {
private val includedButtonsBinding :IncludedButtonsBinding
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val rootBinding = ActivityAwesomeBinding.inflate(inflater, container, false)
includedButtonsBinding = IncludedButtonsBinding.bind(ActivityAwesomeBinding.includes)
return rootBinding.root
}
}
So I completed the first lesson of the Kotlin Course by Google on Udacity and after that I went on to make my own changes to the app that make them look better (just to learn, I don't care about the app). I made some changes like adding dark mode and customizing the UI.
I want the dark mode menu to work properly, like when I click on light mode it should recreate the activity with light mode enabled and should also check the light mode MenutItem. I also want the app to remember the settings so that if I choose Follow System during one session of the app and then close the app, it should keep following the system even after opening the app. I figured this should be done with SharedPreferences but I don't know how to properly do it. As you can see in the video attached below, when I click on any of the dark mode settings options, they don't automatically change the settings, I need to restart the app and only then do I see any changes in the activity that matches to whatever option I selected before closing the app.
Note: I want to mention that I am not very experienced with Android Development or Kotlin, I only started learning 2 months ago. I also want to mention that I DO NOT care about the app itself but I am rather using this app to learn how to get things done. I don't care if my app gets every feature I
would want it to have if I don't also learn how to do those things. It's not the app but the knowledge that I am getting from it that I care about, this is to say that please if you have an answer, do explain how that works.
This video shows the behavior of the app: https://drive.google.com/file/d/1SnN0r351OGF4xQNCtI1wtgouSFVROKzg/view?usp=sharing
I added a toolbar to my layout file of the main (and the only) activity. Here's the xml code for the layout resource:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/diceRollerActivity"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/activity_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:title="#string/app_name" />
</com.google.android.material.appbar.AppBarLayout>
<ImageView
android:id="#+id/dice_image"
android:layout_width="275dp"
android:layout_height="335dp"
android:contentDescription="#+id/diceImage_imageView_description"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.395"
app:srcCompat="#drawable/empty_dice" />
<Button
android:id="#+id/roll_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="#dimen/Container_Button_Padding"
android:text="#string/roll"
android:textAlignment="center"
android:textAllCaps="false"
android:textColor="#color/white"
android:textSize="25sp"
app:backgroundTint="#color/bold_button_color"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/dice_image"
app:layout_constraintVertical_bias="0.32"
app:rippleColor="#color/button_ripple" />
</androidx.constraintlayout.widget.ConstraintLayout>
and here is my the Kotlin code for the same activity:
package com.example.diceroller
import android.content.Context
import android.content.SharedPreferences
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.widget.*
import androidx.appcompat.app.AppCompatDelegate
class MainActivity : AppCompatActivity() {
lateinit var diceImage: ImageView
lateinit var sharedPreferences: SharedPreferences
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(findViewById(R.id.activity_toolbar))
val rollButton: Button = findViewById(R.id.roll_button)
diceImage = findViewById(R.id.dice_image)
rollButton.setOnClickListener {
rollDice()
}
sharedPreferences = getSharedPreferences(getString(R.string.app_name), Context.MODE_PRIVATE)
when (sharedPreferences.getString("Night_Mode_State", getString(R.string.follow_system))) {
getString(R.string.follow_system) -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
getString(R.string.light_mode) -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
getString(R.string.dark_mode) -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
val inflater: MenuInflater = menuInflater
inflater.inflate(R.menu.actionbar, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.follow_system -> sharedPreferences.edit().putString("Night_Mode_State", getString(R.string.follow_system)).apply()
R.id.light_mode -> sharedPreferences.edit().putString("Night_Mode_State", getString(R.string.light_mode)).apply()
R.id.dark_mode -> sharedPreferences.edit().putString("Night_Mode_State", getString(R.string.dark_mode)).apply()
}
return true
}
private fun rollDice() {
when ((1..6).random()) {
1 -> diceImage.setImageResource(R.drawable.dice_1)
2 -> diceImage.setImageResource(R.drawable.dice_2)
3 -> diceImage.setImageResource(R.drawable.dice_3)
4 -> diceImage.setImageResource(R.drawable.dice_4)
5 -> diceImage.setImageResource(R.drawable.dice_5)
else -> diceImage.setImageResource(R.drawable.dice_6)
}
}
}
This gist includes other files that I think are required to answer this question properly, namely: The menu resource file, the colors resource file and the styles resource file: https://gist.github.com/sbeve72/36a71919f1f965c5dcd466db1e099b4f.js"
The Code A and Code B are from the project https://github.com/android/databinding-samples.
The Code B display an icon based fun popularityIcon(view: ImageView, popularity: Popularity) and works well.
I find that project can still work well even if I rename #BindingAdapter("app:popularityIcon") to #BindingAdapter("myok:popularityIcon"), just like Code C, why?
Code A
object BindingAdapters {
#BindingAdapter("app:popularityIcon")
#JvmStatic fun popularityIcon(view: ImageView, popularity: Popularity) {
val color = getAssociatedColor(popularity, view.context)
ImageViewCompat.setImageTintList(view, ColorStateList.valueOf(color))
view.setImageDrawable(getDrawablePopularity(popularity, view.context))
}
...
}
Code B
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="24dp"
android:layout_marginTop="24dp"
android:contentDescription="#string/profile_avatar_cd"
android:minHeight="48dp"
android:minWidth="48dp"
app:layout_constraintBottom_toTopOf="#+id/likes_label"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintVertical_chainStyle="packed"
app:popularityIcon="#{viewmodel.popularity}"/>
Code C
object BindingAdapters {
#BindingAdapter("myok:popularityIcon")
#JvmStatic fun popularityIcon(view: ImageView, popularity: Popularity) {
val color = getAssociatedColor(popularity, view.context)
ImageViewCompat.setImageTintList(view, ColorStateList.valueOf(color))
view.setImageDrawable(getDrawablePopularity(popularity, view.context))
}
...
}
Databinding ignores namespaces. So it removes app: or myok: or anything else. Also, if you put both adapters with the same name but different namespaces, you would get an error telling you that there are more than one adapter for popularityIcon.
You can check the docs for more information.
Note: The Data Binding Library ignores custom namespaces for matching purposes.
you need to update your namespace in your XML were you using this binding.
like below
xmlns:myok="http://schemas.android.com/apk/res-auto"
check below code
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:myok="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
...
</androidx.constraintlayout.widget.ConstraintLayout>
The following sample code CameraFragment.kt and activity_main.xml is from camera-samples project.
It find the NavController using findNavController(requireActivity(), R.id.fragment_container).
I think it's a complex, can I always use findNavController(mView) to find the NavController ? just like Code A?
CameraFragment.kt
private fun updateCameraUi() {
...
Navigation.findNavController(requireActivity(), R.id.fragment_container).navigate(
CameraFragmentDirections.actionCameraToGallery(outputDirectory.absolutePath))
}
activity_main.xml
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true"
tools:context=".MainActivity">
<fragment
android:id="#+id/fragment_container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_graph" />
</FrameLayout>
Code A
private lateinit var mView: View
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mView=view
...
}
Navigation.findNavController(mView).navigate(
CameraFragmentDirections.actionCameraToGallery(outputDirectory.absolutePath))
You don't even need to use Navigation.findNavController(mView) when in a Fragment - you can use NavHostFragment.findNavController(this) to find the NavHostFragment from a Fragment as per the Navigate to a destination documentation.
But yes, you can also use Navigation.findNavController(mView) or use any View from within the Fragment.
You'd only want to use findNavController(requireActivity(), R.id.fragment_container) when you only have the Activity. While it works, there easier ways to do the same thing.