Data is not transferred from activity to fragment - android

I'm trying to write a data transfer from an activity to a fragment, but I'm catching "NullPointerException"
Code MainActivity:
val btn1 = findViewById<Button>(R.id.button)
btn1.setOnClickListener {
BlankFragment2.getNewInstance(321)
val fm = supportFragmentManager
val ft = fm.beginTransaction()
ft.replace(R.id.fragment, BlankFragment2())
ft.commit()
}
Code Fragment:
class BlankFragment2 : Fragment() {
var str: Int = 0
companion object {
fun getNewInstance(args: Int): BlankFragment2 {
val fragment = BlankFragment2()
fragment.arguments?.putInt("one", args)
return fragment
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
str = arguments!!.getInt("one")
return inflater.inflate(R.layout.fragment_blank2, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val txt = view.findViewById<TextView>(R.id.textTest)
txt.text = str.toString()
}
}
I know about protection against null-values, and the problem is that I am sure that the value is passed and null cannot be there

instead of
ft.replace(R.id.fragment, BlankFragment2()
you should use
ft.replace(R.id.fragment, BlankFragment2.getNewInstance(321).
Because your BlankFragment2.getNewInstance(321) statement above is kind of useless to the fragmentManager. FragmentManager is creating fragment using BlankFragment2() as you provided the Fragment in the replace call.
And that is the reason for nullpointerexception because in reality, your Fragment didn't get any int value at all as the Fragment instance used was created with the empty constructor.
And also update your companion object code like below.
companion object {
fun getNewInstance(args: Int): BlankFragment2 {
val fragment = BlankFragment2()
val args = Bundle()
args.putInt("one", args)
fragment.setArguments(args)
return fragment
}
}
because right now your code is actually not setting argument but try to access argument and setting value to it.

Related

passing data from activity to fragment in android studio kotlin(not duplicate, those method is not working)

I am having an activity called Image activity inside it there are 2 fragments called image_display and image_change fragment, for image_activity I am getting data from an adapter(using getIntent), and it's working fine up to here. so I want to send the data
(i.e URL) to the fragment but my method is not working.
my image_activity code is like this
class ImageActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_image)
var gi = getIntent()
var url = gi.getStringExtra("url")
val fragment = FragmentDisplayImage.newInstance(url.toString())
Toast.makeText(this,url , Toast.LENGTH_SHORT).show()
var manager =supportFragmentManager
manager.beginTransaction().commit()
}
}
and my FramentImage.kt is like
private const val ARG_PARAM1 = "url"
class FragmentDisplayImage : Fragment() {
private var param1: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString("url")
var image= view?.findViewById<ImageView>(R.id.Fragimage)
Picasso.get().load(param1).resize(700, 700).centerCrop().into(image);
Toast.makeText(context, param1.toString() , Toast.LENGTH_SHORT).show()
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_display_image, container, false)
}
companion object {
// TODO: Rename and change types and number of parameters
#JvmStatic
fun newInstance(param1: String) =
FragmentDisplayImage().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
}
}
}
}
but still, I can't get my url here on the adapter
I think so you're not starting your fragment.
You have just created fragment object but never opened it using manager.
Please updated your ImageActivity code as follow:
var gi = getIntent()
var url = gi.getStringExtra("url")
val fragment = FragmentDisplayImage.newInstance(url.toString())
val manager: FragmentManager = supportFragmentManager
val transaction: FragmentTransaction = manager.beginTransaction()
transaction.replace(R.id.container, fragment)
transaction.addToBackStack(null)
transaction.commit()
where R.id.container will be Layout inside activity_image where you want to put your fragment.
your activity_image should have
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>

Need Help in Kotlin Android - fragments

I need to get session id to menu fragment. but it doesn't work. In this I get Session ID from Login Activity. Now I need to get that id to Menu fragment. In this one activity loaded five Fragments. I used bundle for load data.
Here's my activity.kt
class Home : AppCompatActivity() {
private val HomeFragment = HomeFragment()
private val CreditsFragment = CreditsFragment()
private val BusFragment = BusFragment()
private val NotificationsFragment = NotificationsFragment()
private val MenuFragment = MenuFragment()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.home)
val sessionId = intent.getStringExtra("EXTRA_SESSION_ID")
textView4.setText(sessionId)
replaceFragment(HomeFragment)
bottomNavBar.setOnNavigationItemSelectedListener{
when (it.itemId){
R.id.menu_home -> replaceFragment(HomeFragment)
R.id.menu_credits -> replaceFragment(CreditsFragment)
R.id.menu_bus -> replaceFragment(BusFragment)
R.id.menu_notification -> replaceFragment(NotificationsFragment)
R.id.menu_menu -> replaceFragment(MenuFragment)
}
true
}
val bundle = Bundle()
bundle.putString("EXTRA_SESSION_ID", sessionId)
val myObj = MenuFragment()
myObj.setArguments(bundle)
}
private fun replaceFragment (fragment:Fragment){
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.fragment_container, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
}
here's my updated menu fragment.kt. I think I have problem in this. can u plzzz help me to find it.
class MenuFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
var sessionId = it.toString()
emailAddressText.setText(sessionId)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_menu, container, false)
}
companion object {
}
}
change activity to this :
val bundle = Bundle()
bundle.putString("EXTRA_SESSION_ID", sessionId)
MenuFragment.setArguments(bundle)
bottomNavBar.setOnNavigationItemSelectedListener{
when (it.itemId){
R.id.menu_home -> replaceFragment(HomeFragment)
R.id.menu_credits -> replaceFragment(CreditsFragment)
R.id.menu_bus -> replaceFragment(BusFragment)
R.id.menu_notification -> replaceFragment(NotificationsFragment)
R.id.menu_menu -> replaceFragment(MenuFragment)
}
true
}
in the fragment you also need to use arguments.getString("EXTRA_SESSION_ID") to retreive sessionId value. and place emailAddressText.setText(sessionId)
in onViewCreated method because in onCreate() method views are not ready yet.
so change the fragment like this :
class MenuFragment : Fragment() {
var sessionId = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
sessionId = it.getString("EXTRA_SESSION_ID","")
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_menu, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
emailAddressText.setText(sessionId)
}
}
The MenuFragment instance you have in your replaceFragment transaction is different from the one where you set the sessionid argument to.
Remove the other instantiation val myObj = MenuFragment() and set arguments on MenuFragment instead.
(Naming convention hint: it's easier to keep types and objects apart if types are CamelCase and types lowerCamelCase. For example, private val menuFragment = MenuFragment().)

Kotlin android data transfer from fragment to dialogFragment

I want to pass some data from Fragment to a DialogFragment (when I click a view by using onClickListener), but the data has empty values in Dialog.
While debugging I found that VO data has no problem. (log comments in my code works correctly)
So, I think that I am not using Bundle correctly.
What can I do to solve this problem?
AccountFragment.class (recyclerview bindViewHolder)
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val accountVO = list[position]
val viewHolder = holder as AccountViewHolder
viewHolder.text_account_title.text = accountVO.title
viewHolder.text_account_bank.text = accountVO.bank
viewHolder.text_account_account.text = accountVO.account
viewHolder.text_account_name.text = accountVO.name
viewHolder.text_account.setOnClickListener() {
// log
// Toast.makeText(context, "${accountVO.title}, ${accountVO.content}", Toast.LENGTH_SHORT).show()
val accountFragment = AccountFragment()
val bundle = Bundle()
bundle.putString("title", accountVO.title)
bundle.putString("content", accountVO.content)
accountFragment.arguments = bundle
AccountDetailDialogFragment().show(activity?.supportFragmentManager as FragmentManager, "dialog_event")
}
}
AccountDetailDialogFragment
class AccountDetailDialogFragment : DialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.activity_account_detail_dialog_fragment, container, false)
view.text_account_detail_title.text = arguments?.getString("title")
view.text_account_detail_content.text = arguments?.getString("content")
isCancelable = false
return view
}
}
You didn't actually set the arguments on your AccountDetailDialogFragment, you set it on your accountFragment (which you didn't even use):
val bundle = Bundle()
bundle.putString("title", accountVO.title)
bundle.putString("content", accountVO.content)
val dialogFragment = AccountDetailDialogFragment()
dialogFragment.arguments = bundle
dialogFragment.show(requireActivity().supportFragmentManager, "dialog_event")
Note that you should make sure your AccountDetailDialogFragment uses the right import for its superclass (you shouldn't need to cast the supportFragmentManager).
try to get this inot onviewCreated
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.text_account_detail_title.text = arguments?.getString("title")
view.text_account_detail_content.text = arguments?.getString("content")
}
Or if its not working than you can try using instance it's a good way to transfer data
change this
AccountDetailDialogFragment().show(activity?.supportFragmentManager as FragmentManager, "dialog_event")
to
accountFragment.show(activity?.supportFragmentManager as FragmentManager, "dialog_event")
this will work :)

Fragment into Bundle

I have a fragment that I would like to use either as a full screen or as a Dialog content.
I'm trying to pass it this way:
companion object {
val DIALOG_TITLE = "DIALOG_TITLE"
fun getInstance(title: String, content: Fragment): BaseCustomDialogFragment {
return BaseCustomDialogFragment().apply {
arguments?.putString(DIALOG_TITLE, title)
activity?.fragmentAdd(content)
}
}
}
Obviously, this solution won't work. As long the Fragment hasn't been attached, we don't have access to the activity.
Is there any way to achieve the same outcome without triggering the load from the Activity?
I found a workaround for this. Instead of passing the Fragment, we include Fragment's class and arguments (Class<T> and Bundle).
Then, we create and add the fragment onViewCreated()
Here is the code:
class BaseCustomDialogFragment: Fragment() {
companion object {
val FRAGMENT_CLASS = "FRAGMENT_CLASS"
val ARGUMENTS_BUNDLE = "ARGUMENTS_BUNDLE"
fun <T> getInstance(title: String, fragmentClass: Class<T>, bundle: Bundle): BaseCustomDialogFragment {
return BaseCustomDialogFragment().apply {
arguments = Bundle()
arguments!!.putString(DIALOG_TITLE, title)
arguments!!.putSerializable(FRAGMENT_CLASS, fragmentClass)
arguments!!.putBundle(ARGUMENTS_BUNDLE, bundle)
}
}
}
private lateinit var className: Class<*>
private lateinit var bundle: Bundle
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
(arguments?.getSerializable(FRAGMENT_CLASS) as? Class<*>)?.let { className = it }
arguments?.getBundle(ARGUMENTS_BUNDLE)?.let { bundle = it }
// Inflate View.
return inflater.inflate(R.layout.fragment_custom_dialog, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setContentUp()
}
private fun setContentUp(){
val fragment = createFragment(className, bundle)
activity?.supportFragmentManager
?.beginTransaction()
?.add(R.id.fragment_dialog_placeholder, fragment)
?.disallowAddToBackStack()
?.commit()
}
private fun <T> createFragment(fragmentClass: Class<T>, arguments: Bundle): Fragment {
val fragment = fragmentClass.newInstance() as Fragment
fragment.arguments = arguments
return fragment
}
I hope it helps to somebody.

dialog containing ViewPager

I want to create a dialog which contain's ViewPager inside it which have 3 pages and all pages have different layout structure. I want a solution by that i can set the layout content programmatically . I think this can be done by making fragments for each page but i don't know how to do this.
I go through these answers but i am not getting idea how to use them in my case.
Viewpager in Dialog?
ViewPager in Custom Dialog
ViewPager in simple Dialog
You can try and build your custom dialog through DialogFragment. Consider the XML layout would contain a ViewPager and the code to go about would be:
class PagerDialog : DialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.element_fragment_pager_dialog, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupPager()
}
private fun setupPager() {
val pagerFragment1 = PagerFragment1.newInstance()
val pagerFragment2 = PagerFragment2.newInstance()
val pagerFragment3 = PagerFragment3.newInstance()
viewPager?.adapter = MyFragmentPagerAdapter(childFragmentManager).apply {
adapterReference = object : PageAdapterInterface {
override var fragmentList: List<Fragment> =
mutableListOf(pagerFragment1, pagerFragment2, pagerFragment3)
}
}
}
companion object {
const val tag = "PagerDialog"
}
}
I have used reference to the list because it might cause leaks when not handled correctly. So the PagerAdapterInterface would look like:
interface PageAdapterInterface {
var fragmentList: List<Fragment>
fun getItemCount() = fragmentList.size
#Throws(StackOverflowError::class)
fun getItemAt(index: Int) : Fragment {
if (index >= fragmentList.size) throw StackOverflowError()
return fragmentList[index]
}
}
Your view pager adapter can make use of this reference in manner that is accessing referentially like:
class MyFragmentPagerAdapter(childFragmentManager: FragmentManager) : FragmentStatePagerAdapter(childFragmentManager){
lateinit var adapterReference: PageAdapterInterface
override fun getItem(p0: Int): Fragment = adapterReference.getItemAt(p0)
override fun getCount(): Int = adapterReference.getItemCount()
}
Finally in your Activity or Fragment on create() or onViewCreated() functions respectively, you can initialize the dialog as shown:
class MyActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// use childFragmentManager if the code is
// used within the Fragment
val prev = supportFragmentManager.findFragmentByTag(PagerDialog.tag)
if (prev != null) {
supportFragmentManager.beginTransaction()
.remove(prev)
.addToBackStack(null)
.commit()
}
PagerDialog().show(supportFragmentManager, PagerDialog.tag)
}
}
Note: DialogFragment is deprecated on > API 28 check out https://developer.android.com/reference/android/app/DialogFragment

Categories

Resources