I am trying to replace a MainFragment fragment with PickPowerFragement fragment but when I press the button in MainFragment to replace MainFragment with PickPowerFragment the app crashes. I was able to successfully load the PickPowerFragment in java as given in tutorial but the app crashes when I tried to do so in Kotlin (just for practice). So how can I replace the Fragment using Kotlin syntax
activity_hero_me.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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="com.example.mandar.herome.Activities.HeroMe"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="25dp">
<FrameLayout
android:id="@+id/ReplaceFrame"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0">
</FrameLayout>
</android.support.constraint.ConstraintLayout>
HeroMe.kt
package com.example.mandar.herome.Activities
import android.app.Activity
import android.app.Fragment
import android.app.FragmentManager
import android.net.Uri
import android.os.Bundle
import com.example.mandar.herome.Fragments.MainFragment
import com.example.mandar.herome.Fragments.PickPowerFragment
import com.example.mandar.herome.R
class HeroMe : Activity() , MainFragment.OnMainFragmentInteractionListener , PickPowerFragment.pickPowerInteractionListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_hero_me)
val manager : FragmentManager = fragmentManager
var fragment : Fragment? = manager.findFragmentById(R.id.ReplaceFrame)
if (fragment == null){
fragment = MainFragment()
manager.beginTransaction().add(R.id.ReplaceFrame,fragment).commit()
}
}
fun loadPickPowerScreen(){
var pickpowerfrag = PickPowerFragment()
fragmentManager.beginTransaction().replace(R.id.ReplaceFrame, pickpowerfrag).addToBackStack(null).commit()
}
override fun onMainFragmentInteraction(uri: Uri) {
}
override fun onPickPowerInteraction(uri: Uri) {
}
}
Here I am calling function loadPickPowerScreen() from MainFragment
I tested If the button( a button I am using to replace MainFragment with pickPowerFragment) works right or not by using it to modify the text on it when the button is clicked and it seems to work just fine.So I guess there shouldn't be any problem with MainFragment.kt
Here is onClick() method from MainFragment.kt
var onClick = View.OnClickListener(){view ->
var heroActivity : HeroMe = HeroMe()
heroActivity.loadPickPowerScreen()
}
and here is fragment PickPowerFragment.kt
package com.example.mandar.herome.Fragments
import android.app.Fragment
import android.content.Context
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.mandar.herome.R
/**
* A simple [Fragment] subclass.
* Activities that contain this fragment must implement the
* [PickPowerFragment.OnFragmentInteractionListener] interface
* to handle interaction events.
* Use the [PickPowerFragment.newInstance] factory method to
* create an instance of this fragment.
*/
class PickPowerFragment : Fragment() {
// TODO: Rename and change types of parameters
private var mParam1: String? = null
private var mParam2: String? = null
private var mListener: pickPowerInteractionListener? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (arguments != null) {
mParam1 = arguments.getString(ARG_PARAM1)
mParam2 = arguments.getString(ARG_PARAM2)
}
}
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val view = inflater!!.inflate(R.layout.fragment_pick_power, container, false)
// Inflate the layout for this fragment
return view
}
// TODO: Rename method, update argument and hook method into UI event
fun onButtonPressed(uri: Uri) {
if (mListener != null) {
mListener!!.onPickPowerInteraction(uri)
}
}
override fun onAttach(context: Context?) {
super.onAttach(context)
if (context is pickPowerInteractionListener) {
mListener = context
} else {
throw RuntimeException(context!!.toString() + " must implement OnFragmentInteractionListener")
}
}
override fun onDetach() {
super.onDetach()
mListener = null
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
*
*
* See the Android Training lesson [Communicating with Other Fragments](http://developer.android.com/training/basics/fragments/communicating.html) for more information.
*/
interface pickPowerInteractionListener {
// TODO: Update argument type and name
fun onPickPowerInteraction(uri: Uri)
}
companion object {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private val ARG_PARAM1 = "param1"
private val ARG_PARAM2 = "param2"
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment PickPowerFragment.
*/
// TODO: Rename and change types and number of parameters
fun newInstance(param1: String, param2: String): PickPowerFragment {
val fragment = PickPowerFragment()
val args = Bundle()
args.putString(ARG_PARAM1, param1)
args.putString(ARG_PARAM2, param2)
fragment.arguments = args
return fragment
}
}
}// Required empty public constructor
logcat after the crash:
Information provided by debugger just before the crash:
Here I add Git Repository link for project Git Android Project: HeroMe
After 2 days of digging, I finally found the solution for my problem. There is just one error I made in the onClick method while converting Java to Kotlin that is resulting in the crash.
Instead of :
var onClick = View.OnClickListener(){view ->
var heroActivity : HeroMe = HeroMe()
heroActivity.loadPickPowerScreen()
}
The code should have been :
var onClick = View.OnClickListener(){view ->
var heroActivity : HeroMe= activity as HeroMe
heroActivity.loadPickPowerScreen()
}
Thank you for everyone who tried to help me.
Clarification for why this code works:
when you write,
var heroActivity : HeroMe = HeroMe()
because of constructor it actually create other object(activity) which is not the same activity which actually loaded. So this new activity is created but not displayed because no startActivity method is called. So,
heroActivity.loadPickPowerScreen()
This method is called on activity which is not started.
Now, this line
var heroActivity : HeroMe= activity as HeroMe
is similar to
getActivity()
form java, which returns the parent activity of fragment. Return type is Activity so we need to case it so we can call functions in that activity.
for fragment adding
getSupportFragmentManager().beginTransaction().add(R.id.container,FragmentLogin()).commit();
for fragment replacing
getSupportFragmentManager().beginTransaction().replace(R.id.container,FragmentLogin()).commit()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With