У меня есть деятельность, в которой есть NavHostFragment. Деятельность получает определенные ценности в своем намерении. Я хочу передать эти данные первому фрагменту, то есть startDestination графа навигации. Я не смог найти никакой документации по этому поводу.
Я уже прошел через этот вопрос на SO, но я не могу найти метод addDefaultArguments для navController.getGraph().
Можно ли передать бандл на startDestination?
@Anmol, да, похоже, это так. Я не понимаю причину удаления addDefaultArguments () в 1.0.0-alpha09. А пока я вернулся к 1.0.0-alpha08.
@Anmol Я добавил ответ согласно последней документации по навигации. stackoverflow.com/a/57607441/3036824




Я тоже не могу найти этот метод. Его не существует в документации по компонентам архитектуры.
Но есть еще один способ установить аргументы для начального пункта назначения:
// Kotlin Code, in Fragment
with(findNavController().graph) {
get(startDestination).addArgument(...)
}
Ну что ж, это документ Kotlin, я только что взглянул на стандартную (Java) документацию ... Но странно, что java и kotlin api не предлагают одинаковые функции.
Кажется, это интересная проблема для решения. Я думаю, что гуглеры упустили большой вариант использования, и это очень странно.
Я просто проверяю 1.0.0-alpha07, у нас есть addDefaultArguments(), и он отлично работает как на Java, так и на kotlin @the_dani
Так они удалили это в alpha09 в java api?
Я так считаю, я разместил вопрос об этом, почему они удалили его, посмотрим, знает ли кто-нибудь.
я также столкнулся с той же проблемой,
Вот как я решил это:
your_activity.xml: т.е. удалить app: navGraph = "@ navigation / nav_graphВот как должен выглядеть ваш XML.
<fragment
android:id = "@+id/nav_host"
android:name = "androidx.navigation.fragment.NavHostFragment"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
app:defaultNavHost = "true"
/>
Добавлять Настройка NavHostFragment Программно в onCreate() активности.
И передать данные пакета с помощью NavGraph.addDefaultArguments(bundleData)api
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.editor_layout)
setupNavigation()
}
private fun setupNavigation() {
val navHostFragment = nav_host as NavHostFragment
val navController = navHostFragment.navController
val navInflater = navController.navInflater
val graph = navInflater.inflate(R.navigation.nav_graph)
graph.addDefaultArguments(intent!!.extras!!) // This is where you pass the bundle data from Activity to StartDestination
navHostFragment.navController.graph = graph
}
Обновлено:
Зависимости в моем файле Project Gradle:
dependencies {
def nav_version = "1.0.0-alpha08"
implementation "android.arch.navigation:navigation-fragment:$nav_version" // use -ktx for Kotlin
implementation "android.arch.navigation:navigation-ui:$nav_version" // use -ktx for Kotlin}
}
ЗАМЕТКА: В версии 1.0.0-alpha09 компонента навигации по какой-то причине у Google нет метода, так как addDefaultArguments() может быть скоро исправлен. Но в более низких версиях есть метод addDefaultArguments(). Я проверил и в java, и в kotlin, поэтому попробуйте использовать 1.0.0-alpha07 или 1.0.0-alpha08.
Я пытаюсь сделать это на Java. Я выполнил ваши шаги, проблема в graph.addDefaultArguments, такого метода под названием addDefaultArguments не существует.
@PraveenSingh проверьте, можете ли вы импортировать класс NavDestination в свой проект. Ссылка: developer.android.com/reference/kotlin/androidx/navigation/…
Я проверил исходный код и увидел, что есть много изменений, касающихся пункта назначения и аргументов навигации. Я думаю, что правильный способ передать аргументы для начала назначения - использовать метод addArgument, примерно так:
val argument1 = 1 //First value
val argument2 = "Value" //Second value
val navArgument1=NavArgument.Builder().setDefaultValue(argument1).build()
val navArgument2=NavArgument.Builder().setDefaultValue(argument2).build()
navController.getGraph().addArgument("Key1",navArgument1)
navController.getGraph().addArgument("Key2",navArgument2)
Может быть, есть способ получше, но я его не нашел.
class MainActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navHostFragment = container as NavHostFragment
val inflater = navHostFragment.navController.navInflater
val graph = inflater.inflate(R.navigation.main_nav)
var data : Data = intent.getParcelableExtra("DATA") as Data
var bundle : Bundle = Bundle()
bundle.putParcelable("DATA", data)
graph.addDefaultArguments(bundle)
graph.addDefaultArguments(intent!!.extras!!)
navHostFragment.navController.graph = graph
}
}
Добавьте приведенный выше код в Activity для отправки данных с помощью навигации
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
var data = NavHostFragment.findNavController(this).graph.defaultArguments.getParcelable("DATA") as Booking
}
Добавьте приведенный выше код в сторону фрагмента
вы можете добавить аргументы в свой график следующим образом
<fragment
android:id = "@+id/exampleFragment"
android:label = "example_fragment"
android:name = "com.example.yourapp.ui.ExampleFragment"
tools:layout = "@layout/example_fragment">
<argument
android:name = "exampleArgs"
app:argType = "reference"
android:defaultValue = "@string/example"/>
</fragment>
https://developer.android.com/guide/navigation/navigation-pass-data
Навигация 1.0.0
val navHostFragment = root_nav_host_fragment as NavHostFragment
val navController = navHostFragment.navController
val navInflater = navController.navInflater
val graph = navInflater.inflate(R.navigation.navigation)
val sectionId = intent.getIntExtra(KEY_SECTION_ID, -1)
val bundle = bundleOf(KEY_SECTION_ID to sectionId)
navHostFragment.navController.setGraph(graph, bundle)
Отвечая на свой вопрос, я нашел правильный подход в обновленной документации по навигации.
На момент написания этого ответа я использую Navigation 2.2.0-alpha01
Если вы хотите передать некоторые данные в начальную точку назначения непосредственно в качестве аргументов активности хоста, вам необходимо вручную установить график навигации хоста внутри метода onCreate () активности хоста, как показано ниже:
Получите navController:
val navController by lazy { findNavController(R.id.<your_nav_host_id>) }
Затем в onCreate() активности хоста
val bundle = Bundle()
bundle.putString("some_argument", "some_value")
navController.setGraph(R.navigation.<you_nav_graph_xml>, bundle)
Или, если вы хотите передать все дополнительные функции намерения, как и в startDestination:
navController.setGraph(R.navigation.<you_nav_graph_xml>, intent.extras)
Поскольку intent.extras вернет только Bundle
When you are setting the navGraph using setGraph() method, you should avoid setting the app:NavGraph attribute in the NavHostFragment definition, because doing so results in inflating and setting the navigation graph twice.
Читая эти аргументы во фрагменте startDestination:
Если вы используете Плагин Safe Args (что очень рекомендуется), то в вашем фрагменте:
private val args by navArgs<DummyFragmentArgs>()
Плагин Safe Args сгенерирует класс Args, добавив Args к имени вашего фрагмента. Например, если ваш фрагмент называется DummyFragment, тогда Safe Args сгенерирует класс с именем DummyFragmentArgs.
где navArgs<> - это функция расширения, определенная в Android KTX
Если вы не используете Android KTX, вы можете получить объект args, например:
val args = DummyFragmentArgs.fromBundle(arguments!!)
После того, как вы получили объект arguments, вы можете просто получить свои аргументы:
args.someArgument
Обратите внимание, как мы передали "some_argument" в качестве аргумента и читаем его как someArgument, используя Safe Args
Если вы не используете Safe Args (хотя нет причин не использовать его), вы можете получить доступ к своим аргументам следующим образом:
arguments?.getString("some_argument")
Все это задокументировано в документации по переходу на компонент навигации здесь: https://developer.android.com/guide/navigation/navigation-migrate#pass_activity_destination_args_to_a_start_destination_fragment
Я нашел решение после некоторого исследования. Он работает с последней версией библиотеки навигации. См. Приведенный ниже код:
Добавьте это в свой макет занятий. Примечание. Мы не устанавливаем аргумент приложение: navGraph в XML-файле. Мы установим его динамически.
<fragment
android:id = "@+id/fragment"
android:name = "androidx.navigation.fragment.NavHostFragment"
android:layout_width = "match_parent"
android:layout_height = "0dp"
android:layout_weight = "1"
app:defaultNavHost = "true" />
В java-файле активности напишите приведенный ниже код и внесите соответствующие изменения. Используйте NavArgument, чтобы передать значение аргумента и добавить аргумент в свой пользовательский Navgraph, а затем установить график.
public class YourActivity extends AppCompatActivity {
private NavArgument nameArg, mailArg;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.profile);
nameArg = new NavArgument.Builder().setDefaultValue("your name").build();
mailArg = new NavArgument.Builder().setDefaultValue("your email id").build();
NavController navController = Navigation.findNavController(this, R.id.fragment);
NavInflater navInflater = navController.getNavInflater();
NavGraph navGraph = navInflater.inflate(R.navigation.nav_profile_graph);
navGraph.addArgument("your name key", nameArg);
navGraph.addArgument("your mail key", mailArg);
navController.setGraph(navGraph);
}
}
Напишите график навигации ниже и добавьте те же ключи аргументов в начальный фрагмент.
<?xml version = "1.0" encoding = "utf-8"?>
<navigation 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/nav_graph"
app:startDestination = "@+id/profile_basic">
<fragment
android:id = "@+id/profile_basic"
android:name = "com.yourpackage.ProfileBasicFragment"
android:label = "Profile Basic"
tools:layout = "@layout/fragment_profile_basic">
<argument android:name = "your name key"
app:argType = "string"/>
<argument android:name = "your mail key"
app:argType = "string"/>
</fragment>
</navigation>
В вашем фрагменте просто выберите значения с помощью функции getArguments ().
String name = getArguments().getString("your name key");
String mail = getArguments().getString("your mail key");
Хотя это поздний ответ, существует очень простой способ передачи пакетов с помощью контроллера навигации / архитектуры навигации:
Фрагмент, который отправит данные
//Best to put in onViewCreated
val navController = findNavController()
//Put in code where you want to start navigation
val b = Bundle()
b.putString("key_1", "Data 1")
b.putString("key_2", "Data 2")
navController.navigate(R.id.action_signupFragment_to_signinFragment,b)
Фрагмент, который получит данные
val data_1: String = arguments?.getString("key_1")?:""
val data_1: String = arguments?.getString("key_2")?:""
В зависимости от типа данных, которые вы отправляете, вам необходимо обновить безопасный вызов или сделать переменные обнуляемыми.
Я просто проверил
1.0.0-alpha07и1.0.0-alpha08, у нас естьaddDefaultArguments(), и он отлично работает как на Java, так и на kotlin. Но для1.0.0-alpha09они удалилиaddDefaultArguments(), это могло быть временным и скоро должно быть исправлено. Так что пока вы можете использовать1.0.0-alpha08.