簡體   English   中英

如何將數據從 Activity 傳遞到 Fragment KOTLIN?

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

我使用帶有 Firebase Auth 和 Firestore 的登錄屏幕,並使用相同的電子郵件鏈接 Firestore 和 Firebase Auth。 我想當我使用電子郵件登錄或注冊到應用程序時,如果成功,它必須傳遞給其他活動的片段,我才能訪問 Firestore。 我嘗試使用 Bundle 和 SafeArgs,但它總是給我 null。我無法解決這個煩人的問題。 我會留下我的代碼。

登錄活動.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 {
            //
        }
    }

主片段.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

<?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>

這里的問題是您在LoginActivity中創建一個 Fragment 實例,為該 Fragment 設置 arguments,然后您啟動一個新的 Activity MainActivity 你沒有對這個 Fragment 引用做任何事情,它在你改變 Activity 之后基本上被遺忘了。

為了更好地理解這一點,您應該提醒自己 Object 面向編程基礎知識 + android 片段 + 活動背后的邏輯。

我建議刪除 LoginActivity 中的 Fragment 創建。 那么你可以做的是:

  1. 首先將 email 添加到 MainActivity Intent extras 中。
  2. 現在您的 MainActivity 中有 email,您可以將它傳遞給您的 navGraph startDestination。 您可以在其他線程中找到有關如何執行此操作的信息,例如: Navigation Architecture Component- Passing argument data to the startDestination
  3. 或者,您也可以在 Fragment 中使用 requireActivity() 來訪問 Activity,但我不推薦這樣做。

正如Mert Ozan所提到的,在 LoginActivity.kt 中創建的 Fragment 引用未在主活動中引用。

而不是嘗試將 Email 地址從登錄活動傳遞到主要活動。 您可以直接在主活動中訪問當前登錄用戶的 email。

就像是:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM