简体   繁体   English

如何将数据从 Activity 传递到 Fragment KOTLIN?

[英]How to pass data from Activity to Fragment KOTLIN?

I use a Login Screen with Firebase Auth and Firestore and linked Firestore and Firebase Auth with same e-mail.我使用带有 Firebase Auth 和 Firestore 的登录屏幕,并使用相同的电子邮件链接 Firestore 和 Firebase Auth。 I am wanting when I login or register to app with e-mail, It have to pass to other Activity's Fragment if it will be successful I can access Firestore.我想当我使用电子邮件登录或注册到应用程序时,如果成功,它必须传递给其他活动的片段,我才能访问 Firestore。 I tried with Bundle and SafeArgs but it always give me null. I can't solve this annoying problem.我尝试使用 Bundle 和 SafeArgs,但它总是给我 null。我无法解决这个烦人的问题。 I will leave my codes.我会留下我的代码。

LoginActivity.kt登录活动.kt

private val db = Firebase.firestore.collection("users")
private val auth = Firebase.auth
private lateinit var binding: ActivityLoginBinding

private fun loginUser(email: String, password: String) {
        if (email.isNotEmpty() && password.isNotEmpty()) {
            CoroutineScope(Dispatchers.IO).launch {
                try {
                    auth.signInWithEmailAndPassword(email, password)
                        .addOnSuccessListener {
                            val fragment = MainFragment()
                            val bundle = Bundle()
                            bundle.putString("mail", email)
                            fragment.arguments = bundle
                            checkLogged()
                            Toast.makeText(this@LoginActivity, "Welcome Again", Toast.LENGTH_SHORT)
                                .show()
                        }
                        .addOnFailureListener {
                            Toast.makeText(this@LoginActivity, it.message, Toast.LENGTH_LONG).show()
                        }.await()
                } catch (e: Exception) {
                    withContext(Dispatchers.Main) {
                        Toast.makeText(this@LoginActivity, e.message, Toast.LENGTH_LONG).show()
                    }
                }
            }
        }
    }

    private fun registerUser(email: String, password: String, user: User) {
        if (email.isNotEmpty() && password.isNotEmpty()) {
            CoroutineScope(Dispatchers.IO).launch {
                try {
                    auth.createUserWithEmailAndPassword(email, password)
                        .addOnSuccessListener {
                            db.document(user.email).set(user)
                            val fragment = MainFragment()
                            val bundle = Bundle()
                            bundle.putString("email", user.email)
                            fragment.arguments = bundle
                            checkLogged()
                            Toast.makeText(
                                this@LoginActivity,
                                "Welcome ${user.name}",
                                Toast.LENGTH_SHORT
                            ).show()
                        }.await()
                } catch (e: java.lang.Exception) {
                    withContext(Dispatchers.Main) {
                        Toast.makeText(this@LoginActivity, e.message, Toast.LENGTH_LONG).show()
                    }
                }
            }
        }
    }

    private fun checkLogged() {
        if (Firebase.auth.currentUser != null) {
            Firebase.auth.currentUser!!.reload()
            startActivity(Intent(this@LoginActivity, MainActivity::class.java))
            finish()
        } else {
            //
        }
    }

MainFragment.kt主片段.kt

class MainFragment : Fragment() {

private val db = Firebase.firestore.collection("users")
private lateinit var binding: FragmentMainBinding

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View {
    binding = FragmentMainBinding.inflate(inflater, container, false)
    if (arguments != null){
        val textName = arguments?.getString("email")
        binding.txtName.text = textName
    }
    return binding.root
}

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

}

nav_graph.xml nav_graph.xml

<?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/mainFragment">
    <fragment
        android:id="@+id/addMealFragment"
        android:name="com.meetozan.caloriecounter.AddMealFragment"
        android:label="fragment_add_meal"
        tools:layout="@layout/fragment_add_meal" />
    <fragment
        android:id="@+id/calendarFragment"
        android:name="com.meetozan.caloriecounter.CalendarFragment"
        android:label="fragment_calendar"
        tools:layout="@layout/fragment_calendar" />
    <fragment
        android:id="@+id/foodsFragment"
        android:name="com.meetozan.caloriecounter.FoodsFragment"
        android:label="fragment_foods"
        tools:layout="@layout/fragment_foods" />
    <fragment
        android:id="@+id/leaderboardFragment"
        android:name="com.meetozan.caloriecounter.LeaderboardFragment"
        android:label="fragment_leaderboard"
        tools:layout="@layout/fragment_leaderboard" />
    <fragment
        android:id="@+id/mainFragment"
        android:name="com.meetozan.caloriecounter.MainFragment"
        android:label="fragment_main"
        tools:layout="@layout/fragment_main">
        <action
            android:id="@+id/action_mainFragment_to_addMealFragment"
            app:destination="@id/addMealFragment" />
        <action
            android:id="@+id/action_mainFragment_to_calendarFragment"
            app:destination="@id/calendarFragment" />
        <action
            android:id="@+id/action_mainFragment_to_foodsFragment"
            app:destination="@id/foodsFragment" />
        <action
            android:id="@+id/action_mainFragment_to_leaderboardFragment"
            app:destination="@id/leaderboardFragment" />
        <argument
            android:name="email"
            app:argType="string"
            app:nullable="true" />
    </fragment>
    <activity
        android:id="@+id/loginActivity"
        android:name="com.meetozan.caloriecounter.LoginActivity"
        android:label="activity_login"
        tools:layout="@layout/activity_login" />
</navigation>

The problem here is that You are creating a Fragment instance in the LoginActivity , setting arguments for that Fragment, and then You start a new Activity MainActivity .这里的问题是您在LoginActivity中创建一个 Fragment 实例,为该 Fragment 设置 arguments,然后您启动一个新的 Activity MainActivity You are not doing anything with this Fragment reference, it is basically forgotten after You change the Activity.你没有对这个 Fragment 引用做任何事情,它在你改变 Activity 之后基本上被遗忘了。

To better understand that, You should remind yourself of Object Oriented Programming basics + logic behind android Fragments + Activities.为了更好地理解这一点,您应该提醒自己 Object 面向编程基础知识 + android 片段 + 活动背后的逻辑。

I suggest to remove the Fragment creation in LoginActivity.我建议删除 LoginActivity 中的 Fragment 创建。 Then what You can do to make it work is to:那么你可以做的是:

  1. Firstly add the email to the MainActivity Intent extras.首先将 email 添加到 MainActivity Intent extras 中。
  2. Now You have the email in your MainActivity and You can pass it to your navGraph startDestination.现在您的 MainActivity 中有 email,您可以将它传递给您的 navGraph startDestination。 You can find info on how to do it in other threads, for example: Navigation Architecture Component- Passing argument data to the startDestination您可以在其他线程中找到有关如何执行此操作的信息,例如: Navigation Architecture Component- Passing argument data to the startDestination
  3. Alternatively you can also use requireActivity() in the Fragment to get to the Activity, but I wouldn't recommend it.或者,您也可以在 Fragment 中使用 requireActivity() 来访问 Activity,但我不推荐这样做。

As mentioned by Mert Ozan , the Fragment reference created in LoginActivity.kt is not referenced in the Main Activity.正如Mert Ozan所提到的,在 LoginActivity.kt 中创建的 Fragment 引用未在主活动中引用。

Instead of trying to pass the Email Address from login activity to main activity.而不是尝试将 Email 地址从登录活动传递到主要活动。 You can access the email of current signed in user directly at the Main Activity.您可以直接在主活动中访问当前登录用户的 email。

Something like:就像是:

private lateinit var auth: FirebaseAuth
...
override fun onCreate(..)..{ // (or onCreateView depending where u want to access the email)
    ...

    auth = FirebaseAuth.getInstance()
    val email = auth.currentUser?.email.toString()

    ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 单击项目时将数据从 recyclerView 传递到新活动 Kotlin - Pass data from recyclerView to new activity when an item is clicked Kotlin 如何将 firebase 数据从一个活动传递到另一个活动? - How to pass firebase data from one activity to another? Firebase 数据检索并将其从片段传递到新活动不起作用 - Firebase data retrieve and passing it from fragment to new activity not working 如何在已经从 Firestore KOTLIN 获取 arrayList 的片段上实现 SearchView - How to implement SearchView on fragment that is already fetching arrayList from firestore KOTLIN 如何从特定片段的活动中禁用 onDestroy 方法? - How to disable an onDestroy method from activity in a specific fragment? 如何使用 Kotlin 从 Firebase 获取特定数据 - How to get specific data from Firebase with Kotlin 如何从Activity返回到Fragment通知他退出账号 - How to return from Activity to Fragment to notify him about the exit from the account 如何从 Firebase 检索其他活动的数据? - How to retrieve data from Firebase on other activity? 如何从片段中的 Firebase 实时数据库中检索数据? - How to Retrieve Data from Firebase Realtime Database in Fragment? 如何从 Firestore (Kotlin) 中的嵌套地图数组中为 RecyclerView 检索数据 - How to retrieve data from nested array of maps in Firestore (Kotlin) for RecyclerView
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM