Lzyprime blog (Github) was created on November 24, 2020.qq and email: 2383518170
Kotlin & Android notes
Lambda. :
Navigation is an important component of Android Jetpack, which was introduced about 3 years ago at Google I/O 2018. Mainly used for organizing fragments, through fragments to achieve the display of different content fragments. Including the switch between the same level, jump between different levels (such as the list item jump details page), instead of the previous jump Activity mode, launch a single Activity mode.
Navigation official Site
withActivity
Comparative benefits:
- Get the same copy
Activity ViewModel
.ViewModel
以Activity
Is unit share, sameActivity
Under theFragment
You can get the same copyViewModel
So if you jump directlyActivity
Data sharing should be handled by itself, either by passing it or fetching it from the global cache, and also by considering replica consistency, which means that if I make changes to the data on one page, all other pages that use the data should be synchronized.
When the Provider plug-in is used to implement state management, the jump to another Route cannot be obtained through The Provider. Of (context) unless the Provider is wrapped in the outer layer of the MaterialApp. Data processing is similar to Android activities. Packages work well in the outermost layer because the MaterialApp generation constructs a Navigator to organize all pages. Save the information with List<_RouteEntry> _history and GlobalKey
_overlayKey. So all pages are children of The MaterialApp.
Navigator2.0, which was recently released with flutter 1.22, allows you to organize pages using List
> pages, which is similar to the Android navigation component, flutter Page is like the Android Fragment
-
Navigation diagrams can be done by dragging boxes with visual tools. Each page is called a “destination”, through the line between, set parameters to achieve the page jump constraints, while you can set the transition animation. All navigation resources are stored in the Navigation folder under the resources folder. Kotlin DSL code is also supported to complete navigation Settings.
-
Safe Args passes data. Safe Arges website address. Ensure safe transfer of data.
In general, it is highly recommended that you only pass the minimum amount of data between destinations. For example, you should pass the key to retrieve the object rather than the object itself, because the total space to hold all the state on Android is limited. “The same applies to flutter. There is no good replica consistency scheme in Flutter, so I cached the beans when the data is parsed. The same data is constructed only once, and then it is all fetched or updated from the cache. The factory constructor is used to cache, generate, update, obtain and other operations of the data invisible, to achieve a simple Loc effect. (TODO: more later)
Note:
- System return button and event handling. jump
Fragment
To intercept and setActivity
The return button event, otherwise the wholeActivity
It’s closed. At the same time, the status updates of other components need to be maintained by themselves. Refer to:Use NavigationUI to update the interface components
This problem also exists in flutter Navigator2.0.
- At the same level
Fragment
Switching requires a rebuild and does not record state. By putting the currentFragmentManager
tonavigation
To achieve a page switch, each switch to rebuildFragment
.
Demo: Add login page and details page
Continue development from the previous demo.
# android navigation demo
# warehouse address: https://github.com/lzyprime/android_demos
# branch: navigation
git clone -b navigation https://github.com/lzyprime/android_demos
Copy the code
1. The import
Use the portal address
If Safe Args is used, the plug-in should be introduced at the top level, or the Bundle should be implemented instead of Safe Args
// project gradle
buildscript {
repositories {
google()
}
// Safe Args
dependencies{...def nav_version = 2.3.1 ""
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"}}Copy the code
// module gradle
plugin {
...
id "androidx.navigation.safeargs.kotlin"
}
dependencies{...// navigation
def nav_version = 2.3.1 ""
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
// Feature module Support
//implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"
// Testing Navigation
//androidTestImplementation "androidx.navigation:navigation-testing:$nav_version"
// Jetpack Compose Integration
/ / implementation "androidx. Navigation: navigation - compose: 1.0.0 - alpha01"
}
Copy the code
2. Navigation chart and destination
Refer to design navigation chart and condition navigation (official website address).
Add a new Android resource, type Navigation, and create a Navigation directory.
Click Add New Destination (Fragment). If it already exists, it will be displayed in the list. Be sure to use Fragment units
Add 3 destinations. The LoginFragment is replaced by the PhotoListFragment after a successful login, so set the popUpTo parameter. Reference navigation to the destination
Each navigation rule has its own ID. Use for NavController. Navigate to implement a jump.
The LoginFragment is the start destination, and the Home page icon is displayed before the name.
2. ToActivity
addNavHost
Add a NavHostFragment to the Layout file and you will receive a warning ⚠ asking you to use the FragmentContainerView as the Fragment container. Click Fix to apply the suggestion.
3. Login function andActivity
Destination switching
Now that the app is ready to launch, it’s going to show you the origin destination which is the LoginFragment.
Demo uses api.unsplash.com/, which actually only requires access_key, so the login page only requires an input box and a login button. The list is requested when you click login and is replaced with a PhotoListFragment page if successful.
// LoginFragment
class LoginFragment : Fragment(R.layout.fragment_login) {
private val viewModel: ListPhotoViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?). {
super.onViewCreated(view, savedInstanceState)
login_btn.setOnClickListener {
val text = access_key_eidt_text.text.toString()
if (text.isEmpty()) {
Toast.makeText(context, "Can't be empty!", Toast.LENGTH_SHORT).show()
} else {
Net.ACCESS_KEY = text
viewModel.refreshListPhotos()
}
}
}
}
Copy the code
Reference navigation to the destination, using NavHost’s NavController to implement the destination jump.
See Using NavigationUI to update the interface component and set the top appBar and system return events accordingly
// MainActivity
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private val viewModel: ListPhotoViewModel by viewModels()
private var loginSuccess = false
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navHost = supportFragmentManager.findFragmentById(R.id.mainNavHost) as NavHostFragment
val navController = navHost.findNavController()
appBarConfiguration = AppBarConfiguration(setOf(R.id.loginFragment, R.id.photoListFragment))
/ / the top appBar
setupActionBarWithNavController(navController, appBarConfiguration)
viewModel.listPhotos.observe(this) {
// The list is not empty, the login succeeded
if(! loginSuccess && it.isNotEmpty()) { loginSuccess =true
Toast.makeText(this."Login successful", Toast.LENGTH_SHORT).show()
navController.navigate(R.id.action_loginFragment_to_photoListFragment)
}
}
}
override fun onSupportNavigateUp(a): Boolean {
// Whether to display the back button
return mainNavHost.findNavController().navigateUp(appBarConfiguration)
|| super.onSupportNavigateUp()
}
override fun onBackPressed(a) {
// The system returns an event
if(! mainNavHost.findNavController().popBackStack()) finish() } }Copy the code
4. Click the picture to enter the details pageSafe Args
Pass image link
Refer to passing data between destinations and visually edit the parameters to be passed on the navigation diagram edit page.
SpecifyAmountFragmentDirections ConfirmationFragmentArgs for plug-in generated automatically, can be found in Java (generated) directory
//PhotoListFragment Jump logic
class PhotoListFragment : Fragment(R.layout.fragment_photo_list) {
...
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val photo = photos[position]
with(holder.itemView as ImageView) {
Glide.with(this).load(photo.urls.raw).into(this)
setOnClickListener {
val directions = PhotoListFragmentDirections.actionPhotoListFragmentToDetailFragment(photo.urls.raw)
this@PhotoListFragment.findNavController().navigate(directions)
}
}
}
...
}
Copy the code
If you use the -ktx version, you can use by navArgs() to get the passed argument
// DetailFragment
class DetailFragment : Fragment(R.layout.fragment_detail) {
private val args by navArgs<DetailFragmentArgs>()
override fun onViewCreated(view: View, savedInstanceState: Bundle?). {
super.onViewCreated(view, savedInstanceState)
Glide.with(imageView).load(args.imageSrc).into(imageView)
}
}
Copy the code