Search code examples
androidkotlinandroid-fragmentsandroid-activityandroid-lifecycle

How to pass data from fragment to activity, when activity is not a parent of fragment


What is the issue:

I want to pass certain "taskId" from Fragment to the Activity. The problem is that this Activity is not a parent of the Fragment, therefore I am unable to pass the data.

What I've tried:

  1. Sending data using intent
  2. Sending data using bundle
  3. Interface (i think interfaces can communicate only when activity is a parent of the fragment?)
  4. SharedViewModel
  5. Passing using local broadcast manager

I guess the main issue is with lifecycle.

In my fragment, I can get data as such and it works:

mTaskContext = (activity as TaskActivityInterface).taskContext
    override fun onOptionsItemSelected(item: MenuItem?): Boolean {
        when (item?.itemId) {
            R.id.barcode_icon -> showScanActivity()
        }
        return super.onOptionsItemSelected(item)
    }

And here is simple intent, but I've tried attaching data to it and receive it in activity, but unfortunately, the value is already null in Activity (it is not null in Fragment)

    private fun showScanActivity() {
        startActivity(Intent(context, TransferScanActivity::class.java))
    }

Here is example with broadcast manager (data is correctly being sent at this point, I've checked it in debug mode):

    private fun showScanActivity() {
        sendDataToActivity(mTaskContext.id)
        startActivity(Intent(context, TransferScanActivity::class.java))
    }


    private fun sendDataToActivity(data: Long) {
        val intent = Intent("SEND_TASKID")
        intent.putExtra("TASK_ID", data)
        LocalBroadcastManager.getInstance(requireContext()).sendBroadcast(intent)
    }
}

and here in activity I register the broadcast receiver in onStart etc, but i dont get anything:

    private val mTaskIdBroadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            Log.d("TaskIdA", "Received broadcast")
                val data = intent?.getLongExtra("TASK_ID", 0)
                Log.d("TaskIdA", "onReceive: $data")
        }
    }

Solution

  • I've found a solution.

    The solution is to simply pass it as an intent, but you have to watch where you try to get this intent. In this particular case, when you try to pass data from fragment to new activity, that is not connected in any way with this fragment, you have to get this intent from onCreate() in new activity.

    Activity:

    private var taskId = 0L
    
    override fun onCreate(savedStateInstance: Bundle?) {
            super.onCreate(savedStateInstance)
            setContentView(R.layout.activity_transfer_scan)
            taskId = intent.getLongExtra("data", 0)
            setUpUi()
        }
    

    Fragment:

        private fun showScanActivity(data: Long) {
            val intent = Intent(requireContext(), TransferScanActivity::class.java)
            intent.putExtra("data", data)
            startActivity(intent)
        }