尝试使用 Kotlin 和 onActivityResult 将数据从 Fragment 发送到 Activity

trying to send data from a Fragment to an Activity with Kotlin and onActivityResult

当在 MainActivity.kt 中按下 'Add Customer' 按钮时,会为结果 CustomerActivity.kt 启动一个新的 Activity。 CustomerActivity 打开片段 (ListFragment.kt),其中包含房间数据库中所有客户的列表。

单击客户时,将打开另一个片段。在UpdateFragment.kt中,显示所有客户信息和一个按钮“选择客户”。单击后,将创建一个 Intent,并将客户信息添加到 Intent。 Main Activity 再次打开,并在意图中传递了选定的客户信息。

如何在 MainActivity.kt 中打开 Intent 以获取来自 UpdateFragment.kt 的信息?并获得对意图传递的客户信息的访问权限?目前我可以使用 UpdateFragment.kt 中的客户信息创建意图并打开 MainActivity.kt 但我不知道如何访问 MainActivity.

中的意图

MainActivity.kt

package com.example.app

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.multiplerecyclerview.CustomerAdapter
import kotlinx.android.synthetic.main.activity_customer.*

const val INDEX = 0

class MainActivity : AppCompatActivity() {

    val list = ArrayList<DataModel>() /*ArrayList that is type Data Model. */

    /* Adapter class is initialized and list is passed in the param. */
    val customerAdapter = CustomerAdapter(this, getItemsList())

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)

        customerButton.setOnClickListener { /* Customer onclick button: Gets taken to the customer screen. */
            val intent = Intent(this@MainActivity, CustomerActivity::class.java)  /* Creating an Intent to go to Customer Activity so a customer can be selected. */
            startActivityForResult(intent,1) /* Starting Activity for result. */
        }

        /* Set the LayoutManager that this RecyclerView will use. */
        customerRecyclerView.layoutManager = LinearLayoutManager(this)

        /* Adapter instance is set to the recyclerview to inflate the items. */
        customerRecyclerView.adapter = customerAdapter

    }

    /* This function is invoked once we return from Activity. */
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if (resultCode == 1) {
            val name: String = data?.getStringExtra("customerName").toString() /* storing the values from arguments returned. */
            val number: String = data?.getStringExtra("customerNumber").toString()
            val postalCode: String = data?.getStringExtra("postalCode").toString()
            val address: String = data?.getStringExtra("address").toString()

        }

    }

    private fun getItemsList(): ArrayList<DataModel> {

        list.add(DataModel("Todd Philips","123 Fake Street","012801212", OrderAdapter.CUSTOMER_ADD))

        return list
    }

}

CustomerActivity.kt

package com.example.app

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class CustomerActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_customer)
    }

}

activity_customer.xml

<?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=".CustomerActivity">

    <fragment
        android:id="@+id/fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/app_nav" />

</androidx.constraintlayout.widget.ConstraintLayout>

ListFragment.kt

package com.example.app

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.app.viewmodel.AppViewModel
import com.example.app.fragments.list.ListAdapter
import kotlinx.android.synthetic.main.fragment_list.view.*

class listFragment : Fragment() {

    private lateinit var appViewModel: appViewModel

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        val view = inflater.inflate(R.layout.fragment_list, container, false)
        //val search = findViewById<>

        // RecyclerView
        val adapter = ListAdapter()
        val recyclerView = view.recyclerview
        recyclerView.adapter = adapter
        recyclerView.layoutManager = LinearLayoutManager(requireContext())

        //CustomerViewModel
        appViewModel = ViewModelProvider(this).get(AppViewModel::class.java)
        appViewModel.readAllData.observe(viewLifecycleOwner, Observer {customer ->
            adapter.setData(customer)
        })


        view.floatingActionButton.setOnClickListener {
            findNavController().navigate(R.id.action_listFragment_to_addFragment)
        }
        return view
    }
}

UpdateFragment.kt

package com.example.app.fragments.update

import android.content.Intent
import androidx.appcompat.app.AlertDialog
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.appcompat.widget.AlertDialogLayout
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.example.app.*
import com.example.app.model.Customer
import com.example.app.viewmodel.APPViewModel
import kotlinx.android.synthetic.main.fragment_update.*
import kotlinx.android.synthetic.main.fragment_update.view.*

class UpdateFragment : Fragment() {

    private val args by navArgs<UpdateFragmentArgs>()
    private lateinit var appViewModel: APPViewModel

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        val view = inflater.inflate(R.layout.fragment_update, container, false)

        appViewModel = ViewModelProvider(this).get(APPViewModel::class.java)

        view.updateTextName.setText(args.currentCustomer.name)
        view.updateTextNumber.setText(args.currentCustomer.mobile)
        view.updatePostalAddress.setText(args.currentCustomer.eircode)
        view.updateTextAddress.setText(args.currentCustomer.address)

        view.updateBtn.setOnClickListener {
            updateItem()
        }

        view.deleteBtn.setOnClickListener {
            deleteItem()
        }

        view.pickBtn.setOnClickListener {
            val name = updateTextName.text.toString()
            val number = updateTextNumber.text.toString()
            val postalCode = updatePostalAddress.text.toString()
            val address = updateTextAddress.text.toString()

            Toast.makeText(requireContext(), "Pick Button Clicked!", Toast.LENGTH_SHORT).show()
           //val intent = Intent(getActivity(), OrderActivity::class.java)
           
            //Creating the intent to return to MainActivity with customer information
            val intent = Intent(activity, MainActivity::class.java)
            activity?.startActivity(intent)

            intent.putExtra("customerName", name)
            intent.putExtra("customerNumber", number)
            intent.putExtra("postalCode", postalCode)
            intent.putExtra("address", address)

            activity?.startActivity(intent)


           // setResult(RESULT_CODE_2, intent) // Tried using this code to finish the activity and return to main
           // finish() /* Ending the  Activity. */
        }

        return view
    }

    private fun updateItem() {
        val name = updateTextName.text.toString()
        val number = updateTextNumber.text.toString()
        val postalCode = updatePostalAddress.text.toString()
        val address = updateTextAddress.text.toString()

        val customer = Customer(args.currentCustomer.id, name,address,postalCode,number)

        posViewModel.updateCustomer(customer)
        Toast.makeText(requireContext(), "Successfully updated!", Toast.LENGTH_LONG).show()
        // Returning to the List Fragment
        findNavController().navigate(R.id.action_updateFragment_to_listFragment)

    }

    private fun deleteItem() {
       
    }

}


在 Main 中单击了此按钮Activity

更新

我在 UpdateFragment.kt,我想创建一个关于客户的意图和额外信息,并将额外信息发送到 MainActivity.kt

问题是关于接收发送到 MainActivity 的信息。我在 MainActivity 中使用 onActivityResult 来接收来自 UpdateFragment 的意图。但是该函数没有被调用。 UpdateFragment.kt

    view.pickBtn.setOnClickListener {
            val name = updateTextName.text.toString()
            val number = updateTextNumber.text.toString()
            val postalCode = updatePostalAddress.text.toString()
            val address = updateTextAddress.text.toString()

            Toast.makeText(requireContext(), "Pick Button Clicked!", Toast.LENGTH_SHORT).show()
           //val intent = Intent(getActivity(), MainActivity::class.java)
       /*
            val intent = Intent(activity, MainActivity::class.java)

            intent.putExtra("customerName", name)
            intent.putExtra("customerNumber", number)
            intent.putExtra("postalCode", postalCode)
            intent.putExtra("address", address)

            activity?.startActivity(intent)
*/
            startActivityForResult(Intent(context, OrderActivity::class.java), 141)

           // setResult(RESULT_CODE_2, intent)
           // finish() /* Ending the  Activity. */
        }

        return view
    }

    override fun startActivityForResult(intent: Intent?, requestCode: Int) {

        if (requestCode == 141) {
            intent!!.putExtra("customerName", "John")
            intent.putExtra("customerNumber", "087212")
            intent.putExtra("postalCode", "V1H7")
            intent.putExtra("address", "123 Fake Street")

            onActivityResult(1, 2, intent)
        }

    }

MainActivity.kt


/* This function is invoked once we return from Activity. */
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

       
            val name: String = data?.getStringExtra("customerName").toString() /* storing the values from arguments returned. */
            val number: String = data?.getStringExtra("customerNumber").toString()
            val postalCode: String = data?.getStringExtra("postalCode").toString()
            val address: String = data?.getStringExtra("address").toString()

    }

我没有阅读您写的所有内容,但在您的 Activity class 中,您正在检查错误的结果代码。改成请求码

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)

    if (resultCode == RESULT_OK) {
        if (requestCode== 1) {
           val name: String = data?.getStringExtra("customerName").toString() /* storing the values from arguments returned. */
           val number: String = data?.getStringExtra("customerNumber").toString()
           val postalCode: String = data?.getStringExtra("postalCode").toString()
           val address: String = data?.getStringExtra("address").toString()
        }
    }
}

抱歉没有完全检查代码,但为了达到您的预期结果,您可以试试这个:

从您的 UpdateFragment 打开 MainActivity ->

您需要从片段本身执行 startActivityForResult。不要使用 activity?.startActivity()。通过使用 UpdateFragment 中的 startActivityForResult,您可以在 UpdateFragment 本身中实现 ​​onActivityResult() 并在调用 setResult() 和 finish() 时从 MainActivity 获取结果。

编辑: 我的意思是从片段开始 activity 并在片段本身中实现 ​​onActivityResult 。这样你的 activity 将从片段开始,一旦完成,就会将结果提供给片段。

UpdateFragment.kt

view.pickBtn.setOnClickListener {
        val name = updateTextName.text.toString()
        val number = updateTextNumber.text.toString()
        val postalCode = updatePostalAddress.text.toString()
        val address = updateTextAddress.text.toString()

        Toast.makeText(requireContext(), "Pick Button Clicked!", Toast.LENGTH_SHORT).show()
       //val intent = Intent(getActivity(), MainActivity::class.java)
   
        val intent = Intent(activity, MainActivity::class.java)

        intent.putExtra("customerName", name)
        intent.putExtra("customerNumber", number)
        intent.putExtra("postalCode", postalCode)
        intent.putExtra("address", address)

        //activity?.startActivity(intent)

        startActivityForResult(intent, 141)

       // setResult(RESULT_CODE_2, intent)
       // finish() /* Ending the  Activity. 
    }

    return view
}

/* This function is invoked once we return from Activity. */
        override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
            super.onActivityResult(requestCode, resultCode, data)
            val name: String = data?.getStringExtra("customerName").toString() /* storing the values from arguments returned. */
        val number: String = data?.getStringExtra("customerNumber").toString()
        val postalCode: String = data?.getStringExtra("postalCode").toString()
        val address: String = data?.getStringExtra("address").toString()
}
}

并且在您的主 activity 中,覆盖 onActivityResult 并调用 super()。

MainActivity.kt:

/* This function is invoked once we return from Activity. */
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
//The activity gets the first shot at onActivityResult. 
//If we don't want to do any process here, then we need to call super.onActivityResult() 
//which will then allow the fragment's onActivityResult to be called. 
//This ONLY works when we start the activity from the fragment.
        super.onActivityResult(requestCode, resultCode, data)
    }

如果需要,可以参考这个答案here在fragment中获取onActivityResult回调