How to open a fragment with button click in recycler view - android

class Crypto : Fragment(R.layout.fragment_crypto) {
private lateinit var recyclerView: RecyclerView
private lateinit var cryptolist: ArrayList<crypro_data>
private lateinit var cryptoAdapter: cryptoAdapter
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView = view.findViewById(R.id.recyclerview)
recyclerView.setHasFixedSize(true)
recyclerView.layoutManager = LinearLayoutManager(activity)
cryptolist = ArrayList()
cryptolist.add(crypro_data(R.drawable.ic_baseline_history_24,"dolar"))
cryptolist.add(crypro_data(R.drawable.ic_baseline_history_24,"lari"))
cryptolist.add(crypro_data(R.drawable.ic_baseline_history_24,"lira"))
cryptolist.add(crypro_data(R.drawable.ic_baseline_history_24,"sterlingi"))
cryptolist.add(crypro_data(R.drawable.ic_baseline_history_24,"dolar"))
cryptolist.add(crypro_data(R.drawable.ic_baseline_history_24,"lari"))
cryptolist.add(crypro_data(R.drawable.ic_baseline_history_24,"lira"))
cryptolist.add(crypro_data(R.drawable.ic_baseline_history_24,"sterlingi"))
cryptolist.add(crypro_data(R.drawable.ic_baseline_history_24,"dolar"))
cryptolist.add(crypro_data(R.drawable.ic_baseline_history_24,"lari"))
cryptoAdapter = cryptoAdapter(cryptolist)
recyclerView.adapter = cryptoAdapter
}
}
this is my code on a fragment where i have recyclerview
i would like to know if it would be possible to open a same fragment when clicked on any of the items in the recyclerview.
but each item has to transfer its unique id to opened fragment in order to find out which button was clicked.

To open a Fragment with a button click in a RecyclerView, you can use the setOnClickListener method on the button in your RecyclerView's adapter together with a click listener in the Fragment from where you create the adapter.
Here is an example of how you can do this in an adapter:
class ImageAdapter(private var imageModel: List<ImageModel>) : RecyclerView.Adapter<ImageAdapter.PostViewHolder>() {
...
//The click listener
var onButtonClick: ((ImageModel) -> Unit)? = null
override fun onBindViewHolder(holder: PostViewHolder, position: Int) {
...
//Set the click listener on the button you have in your RV element
holder.itemView.button.setOnClickListener {
//Clicked
onButtonClick?.invoke(imageModel[position])
}
}
}
In your Fragment, you can implement the listener and set it to the adapter and handle the transition:
lass YourFragment : Fragment() {
...
private val imageAdapter = ImageAdapter(listOf())
...
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
imageAdapter.onButtonClick = { imageModel ->
// Handle the button click here
// open a new fragment
val fragment = AnotherFragment()
val fragmentManager = childFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
// Pass object as extra
bundle.putParcelable("key", imageModel)
fragment.arguments = bundle
fragmentTransaction.replace(R.id.fragment_container, fragment)
fragmentTransaction.addToBackStack(null)
fragmentTransaction.commit()
}
}
}
And in the AnotherFragment, you can retrieve the object from the arguments property in the onCreate method:
class AnotherFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Retrieve object from extra
val myObject = arguments?.getParcelable<MyObject>("key")
}
}
In this example, the class ImageModel,should implement the Parcelable interface.
Happy Coding!

Related

Android fragment creation without constructor params

I have a viewpager2 adapter
class SectionPager2(fragment: Fragment): FragmentStateAdapter(fragment) {
private val fragmentList = mutableListOf<Fragment>()
override fun getItemCount() = fragmentList.size
override fun createFragment(position: Int) = fragmentList[position]
fun addFragment(position: Int, fragment: Fragment) {
fragmentList.add(position, fragment)
}
}
I use it along with a Tablayout like this
val sectionPagerAdapter = SectionPager2(this)
for (item in gradeSectionMajorOrdered) {
var title = ""
fragment = HomeDetailTempFragment.newInstance(thisFragment, item.majors!!, item.gradeSectionId)
gradeSectionIds.add(item.gradeSectionId)
for (i in viewModel.gradeSections.value?.result!!) {
if (i.id == item.gradeSectionId) title = i.name
}
majorItems.add(item.majors)
gradeSectionId = item.gradeSectionId
sectionPagerAdapter.addFragment(gradeSectionMajorOrdered.indexOf(item), fragment)
fragmentTitleList.add(gradeSectionMajorOrdered.indexOf(item), title)
}
Here I get HomeDetailTempFragment data from a server, the problem is that when I use
HomeDetailTempFragment.newInstance(thisFragment, item.majors!!, item.gradeSectionId) the code for example generates 3 the same data HomeDetailTempFragment view in viewpager but if I change this and remove companion object newInstance from HomeDetailTempFragment it works correctly and we all know what's gonna happen sometimes on some devices we get unable to intantiate fatal error.
This class does not work correctly:
#SuppressLint("ValidFragment")
class HomeDetailTempFragment : BaseFragment(), MajorRecyclerViewAdapter.IMajorRV {
companion object {
private lateinit var listener: OnClick
private lateinit var items: List<MajorGrades>
private var gradeSectionId = 0
fun newInstance(
listener: HomeDetailFragment,
items: List<MajorGrades>,
gradeSectionId: Int,
) = HomeDetailTempFragment().also {
this.listener = listener
this.gradeSectionId = gradeSectionId
this.items = items
}
}
private lateinit var mContext : Context
private lateinit var binding: FragmentHomeDetailTempBinding
override fun onCreateView(inflater : LayoutInflater,
container : ViewGroup?,
savedInstanceState : Bundle?) : View {
binding = FragmentHomeDetailTempBinding.inflate(layoutInflater)
return binding.root
}
override fun onViewCreated(view : View, savedInstanceState : Bundle?) {
super.onViewCreated(view, savedInstanceState)
mContext = requireContext()
binding.rvGradeMajor.adapter = MajorRecyclerViewAdapter(context = mContext,
majors = items,
gradeSectionId = gradeSectionId,
listener = this)
}
override fun onGradeMajorClick(majorItem : MajorGrades, gradeItem : MajorGrades) {
listener.onGradeMajorClick(gradeSectionId, majorItem, gradeItem)
}
}
If I change the class this way it works as expected
#SuppressLint("ValidFragment")
class HomeDetailTempFragment(private val listener : OnClick,
private val items : List<MajorGrades>,
private val gradeSectionId : Int)
: BaseFragment(), MajorRecyclerViewAdapter.IMajorRV {
private lateinit var mContext : Context
private lateinit var binding: FragmentHomeDetailTempBinding
override fun onCreateView(inflater : LayoutInflater,
container : ViewGroup?,
savedInstanceState : Bundle?) : View {
binding = FragmentHomeDetailTempBinding.inflate(layoutInflater)
return binding.root
}
override fun onViewCreated(view : View, savedInstanceState : Bundle?) {
super.onViewCreated(view, savedInstanceState)
mContext = requireContext()
binding.rvGradeMajor.adapter = MajorRecyclerViewAdapter(context = mContext,
majors = items,
gradeSectionId = gradeSectionId,
listener = this)
}
override fun onGradeMajorClick(majorItem : MajorGrades, gradeItem : MajorGrades) {
listener.onGradeMajorClick(gradeSectionId, majorItem, gradeItem)
}
}
Both your approaches to creating fragments are wrong.
In the first case you write data to companion object of HomeDetailTempFragment. This is same as writing to a static variable in Java. So you get only the data you wrote last - for the last fragment.
The second case would fail as soon as Android system decided to recreate your fragment, for example on screen rotation, because it would call empty constructor. But I assume it just fails to compile.
The correct way is to use setArguments in newInstance and getArguments in onViewCreated (or onCreateView). See this question for more info, including Kotlin implementation.
However I suspect you won't be able to put List<MajorGrades> into the Bundle. Also Bundles have limited size. Instead I'd suggest using a shared ViewModel for the data and passing only fragment's position via the arguments.

Passing adapter text to fragment creating problems

I want to pass data to fragment so when items in recycler adapter clicked it pass item name (sample[position].text1) fetched from firebase to fragment. I tried bundle, interface but getting error in both methods.I searched on internet but not find anything which solve my problem. mainActivity(splash screen) is only Activity in my App rest are fragments.
I used inner class method, I'm getting result but in another fragment where this adapter attached and I don't want it there.
Problem: pass sample[position].text1 to fragment so I can pass it to db.collection("here") to fetch data from Firebase.
Adapter
class dashboard_gridlayout_adapter(
private val sampledata: ArrayList<daxhboard_gridlayout_data>
): Adapter<dashboard_gridlayout_adapter.dashboard_viewholder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): dashboard_viewholder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.dashboard_gridlayout_single_item_design, parent, false)
return dashboard_viewholder(itemView)
}
override fun onBindViewHolder(holder: dashboard_viewholder, position: Int) {
Glide.with(holder.itemView).load(sampledata[position].imageResource)
.placeholder(R.drawable.ic_baseline_history_icon)
.into(holder.imageView)
holder.textView.text = sampledata[position].text1
holder.itemView.setOnClickListener {
val appCompatActivity = it.context as AppCompatActivity
appCompatActivity.supportFragmentManager.beginTransaction()
.replace(R.id.Activity_frag_container, service_providers_list())
.addToBackStack(null)
.commit()
}
}
override fun getItemCount() = sampledata.size
inner class dashboard_viewholder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val imageView: ImageView = itemView.dashboard_adapter_image
val textView: TextView = itemView.dashboard_adapter_text
}
}
Fragment
class service_providers_list : Fragment(){
private var db = FirebaseFirestore.getInstance()
private lateinit var service_list_recycler: RecyclerView
var servlist = ArrayList<service_provider_list_data>()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.service_providers_list, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
getserviceproviderdata()
service_list_recycler = service_provider_recycle_view.findViewById(R.id.service_provider_recycle_view)
service_provider_recycle_view.layoutManager = LinearLayoutManager(this.requireContext())
service_provider_recycle_view.setHasFixedSize(true)
}
private fun getserviceproviderdata() {
db.collection("Barber").orderBy("dist")
.get()
.addOnSuccessListener { documents ->
servlist.clear()
for (document in documents) {
val imgurl = document.data["imageResource"].toString()
val prov_name = document.data["provider_name"].toString()
val prov_address = document.data["provider_address"].toString()
val prov_rate = document.data["provider_rating"].toString()
val prov_dist = document.data["provider_distance"].toString()
servlist.add(service_provider_list_data(imgurl, prov_name, prov_address, prov_rate, prov_dist))
service_provider_recycle_view.adapter = service_provider_list_adapter(servlist)
}
}
.addOnFailureListener { exception ->
Log.e("serf", "Error getting documents: ", exception)
}
}
}
MainActivity (It's a splash screen)
class MainActivity : AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
#Suppress("DEPRECATION")
Handler().postDelayed(
{
supportFragmentManager.beginTransaction().replace(R.id.Activity_frag_container,Login_Screen()).commit()
},
1500
)
}
}
I solved this problem
just add new parameter(need to pass) inside replace in adapter
holder.itemView.setOnClickListener {
val datashares = sampledata[position].text1
val appCompatActivity = it.context as AppCompatActivity
appCompatActivity.supportFragmentManager.beginTransaction()
.replace(R.id.Activity_frag_container, service_providers_list(datashares))
.addToBackStack(null)
.commit()
}
and inside fragment just add
class service_providers_list(datashares: String) Fragment(){
//variable declaration
private var datasharae = datashares
(inside function where i wnt to add code i.e getserviceproviderdata() )
fun getserviceproviderdata() {
db.collection(datasharae)
.............
..............
......rest code.....
.........}

Is it right to put replaceFragment inside onBindViewHolder?

I'm learning Jetpack by changing the Demo from codelabs.
What I changed is move the code of the MainActivity.kt into a fragment and jump between fragments.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
replaceFragment(WordListFragment())
}
}
// Extension function to replace fragment
fun AppCompatActivity.replaceFragment(fragment: Fragment){
val fragmentManager = supportFragmentManager
val transaction = fragmentManager.beginTransaction()
transaction.replace(R.id.host,fragment)
transaction.addToBackStack(null)
transaction.commit()
}
When we click the items, we will call replaceFragment inside WordListAdapter and go to another fragment as follows:
class WordListAdapter : RecyclerView.Adapter<WordListAdapter.WordViewHolder>() {
...
override fun onBindViewHolder(holder: WordViewHolder, position: Int) {
val current = words[position]
holder.wordItemView.text = current.word
holder.itemView.setOnClickListener {
// fire recyclerView click event
val activity = it.context as AppCompatActivity
val args = Bundle()
// Send string data as key value format
args.putString("word", current.word)
val fragment = WordDefinitionFragment()
fragment.arguments = args
activity.replaceFragment(fragment)
}
}
I just wondering if it's the right way to put replaceFragment inside the onBindViewHolder ?
In my opinion RecyclerView.Adapter should only bind immutable data and pass clicks via callbacks, and the Activity should be the one to change fragment. In my opinion you should do something like this:
class WordListAdapter(private val onViewHolderClicked: (String) -> Unit) : RecyclerView.Adapter<WordListAdapter.WordViewHolder>() {
...
override fun onBindViewHolder(holder: WordViewHolder, position: Int) {
val current = words[position]
holder.wordItemView.text = current.word
holder.itemView.setOnClickListener {
onViewHolderClicked(current.word)
}
}
and in Activity:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
replaceFragment(WordListFragment())
}
...
fun setupRecyclerView() {
...
val adapter = WordListAdapter() { word ->
val args = Bundle()
// Send string data as key value format
args.putString("word", word)
val fragment = WordDefinitionFragment()
fragment.arguments = args
replaceFragment(fragment)
}
}
}

How to manipulate fragment dynamically in view pager when data returned by fragment is empty

In my activity I am setting ViewPager,TabLayout and adding two fragment instance in a list. Then i am passing that list to ViewPagerAdapter .Responsibility of fragment is to fetch data from api call and show it in a list .
I am taking two instance of fragment because api returns two list of data that need to be show in tab fashion(One list in one tab and one in another). But when viewpager adapter returns fragment , if one data list is empty then I am getting empty screen in Tab-0 .
How to dynamically detect data size (here confused , because need to call fragment) and populate tab based on that.
ActivityOne.kt
class ActivityOne : BaseActivity() {
lateinit var item: ArrayList<HistoryTabItem>
lateinit var tabLayout: Tabs
val InfoViewpagerAdapter:InfoVIewPagerAdapter by lazy { InfoVIewPagerAdapter(supportFragmentManager, ArrayList()) }
fun newInstance(context: Context): Intent {
return Intent(context, InfoFragment::class.java)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.info_tabview)
getFragments()
InfoViewpagerAdapter.arrayList = item
tabLayout = findViewById(R.id.tabsnfo_type)
val viewPager = findViewById<ViewPager>(R.id.view_pager_info_type)
viewPager.adapter = InfoViewpagerAdapter
tabLayout.setupWithViewPager(viewPager)
}
fun getFragments() {
item = ArrayList()
val HistoryTabItemSeller = HistoryTabItem()
HistoryTabItemSeller.fragment = InfoFragment.createInstance()
item.add(HistoryTabItemSeller)
val HistoryTabItemBuyer = HistoryTabItem()
HistoryTabItemBuyer.fragment = InfoFragment.createInstance()
item.add(HistoryTabItemBuyer)
}
}
InfoViewPageradapter
class InfoVIewPagerAdapter(fm: FragmentManager, var arrayList: ArrayList<HistoryTabItem>) : FragmentPagerAdapter(fm) {
override fun getItem(position: Int): Fragment {
return arrayList[position].fragment
}
override fun getCount(): Int {
return arrayList.size
}
}
Fragment
class InfoFragment : BaseDaggerFragment(), InfoContract.View {
var isTickerShow: Boolean? = false
var tickerMessage: String? = null
lateinit var allTransactionList: ArrayList<Any>
#Inject
lateinit var infoPresenter: HoldInfoPresenter
val infoAdapter: InfoAdapter by lazy {
InfoAdapter(ArrayList()) }
lateinit var fakelist: ArrayList<Any>
companion object {
fun createInstance(): Fragment {
return InfoFragment()
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_container_info, container, false)
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initView()
infoPresenter.attachView(this)
infoPresenter.getInfo()
}
fun initView() {
rv_container.layoutManager = LinearLayoutManager(context)
rv_container.adapter = infoAdapter
}
override fun renderInfo(depositHistory: DepositHistory?) {
var resultList = ArrayList<Any>()
depositHistory?.let {
resultList = combinedTransactionList(it.sellerData as ArrayList<SellerDataItem>, it.buyerData as ArrayList<BuyerDataItem>)
isTickerShow = it.tickerMessageIsshow
tickerMessage = it.tickerMessageId
}
infoAdapter.list.clear()
infoAdapter.list.addAll(resultList)
infoAdapter.notifyDataSetChanged()
}
fun combinedTransactionList(arrayList: ArrayList<SellerDataItem>, arrayList1: ArrayList<BuyerDataItem>): ArrayList<Any> {
allTransactionList = ArrayList()
allTransactionList.clear()
allTransactionList.addAll(arrayList)
allTransactionList.addAll(arrayList1)
return allTransactionList
}
}
The best option is to fetch data in the activity and then show that tab layout with 2 tabs or just one tab. You would use it with a shared view model, but I see you don't use view models here.
You can also just set the list in createInstance() method in Fragment when it isn't empty.
The third option is to fetch data in Fragment and then send information to activity that the list is empty and hide the specific tab.

is it possible to get `RecyclerView` from Fragment?

trying to get RecyclerView from this layout :
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".listFragment">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/recyclee">
</android.support.v7.widget.RecyclerView>
into main activity class :
private var mBlogList = findViewById<RecyclerView>(R.id.recyclee)
getting error :
java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.Window$Callback android.view.Window.getCallback()' on a null object reference
any help please :)
edit 1
i use kotlin extension now
import kotlinx.android.synthetic.main.fragment_list.*
class MainActivity : AppCompatActivity() {
private lateinit var mBlogList : RecyclerView
in onCreate method :
mBlogList = recyclee
but the same error still exist
edit 2
listFragment code :
class listFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_list, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclee != null
}
companion object {
fun newInstance(): listFragment = listFragment()
}
}
edit 3
whole MainActivity code:
//this app supposed to read from FirebaseDatabase
//into Recycler view
//the RecyclerView is into Fragment layout
//i use Fragments into FrameLayout in the activity_main.xml
// the RecyclerView should be shown when navigatoinBar is clicked
//or on start of MainActivity
class MainActivity : AppCompatActivity() {
private var mDatabase:DatabaseReference? = null
private lateinit var mBlogList : RecyclerView
private var query:Query?=null
private var options:FirebaseRecyclerOptions<Blog>?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//start listFragment , RecyclerView is there
val mFragment = listFragment.newInstance()
//openFragment method is below
openFragment(mFragment)
//navigation bottom onclicklistener
navBar.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
//get data from database
mDatabase=FirebaseDatabase.getInstance().getReference().child("mall")
mDatabase?.keepSynced(true)
//here i should have recyclee but it is null i don't know why
mBlogList = recyclee
mBlogList.setHasFixedSize(true)
mBlogList.layoutManager = LinearLayoutManager(this)
//query of database
query = mDatabase?.orderByKey()
}
private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
//there are 4 icons in the navigation_bottom_bar
//now we are talking about listNav icon only because it is realted
// with listFragment
when (item.itemId) {
R.id.listNav -> {
val mFragment = listFragment.newInstance()
openFragment(mFragment)
return#OnNavigationItemSelectedListener true
}
R.id.cartNav -> {
val mFragment = cartFragment.newInstance()
openFragment(mFragment)
return#OnNavigationItemSelectedListener true
}
R.id.supportNav -> {
val mFragment = supportFragment.newInstance()
openFragment(mFragment)
return#OnNavigationItemSelectedListener true
}
R.id.accountNav -> {
val mFragment = accountFragment.newInstance()
openFragment(mFragment)
return#OnNavigationItemSelectedListener true
}
}
false
}
private fun openFragment(fragment: Fragment) {
//open Fragment into FrameLayout in the main_activity.xml
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.mainFrame, fragment)
transaction.addToBackStack(null)
transaction.commit()
}
override fun onStart() {
super.onStart()
//set options for FirebaseRecyclerAdapter
options = FirebaseRecyclerOptions.Builder<Blog>()
.setQuery(query!!, Blog::class.java)
.build()
//set custom adapter
val mAdapter = object : FirebaseRecyclerAdapter<Blog, BlogViewHolder>(
options!!) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BlogViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.cardview, parent, false)
return BlogViewHolder(view)}
override fun onBindViewHolder(holder: BlogViewHolder, position: Int, model: Blog) {
holder.setTitle(model.title)
holder.setDes(model.des)
holder.setImage(applicationContext, model.image)
}
}
mBlogList.adapter = mAdapter
}
inner class BlogViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var mView:View= itemView
//set title, des amd image with data we got from database
fun setTitle(title:String){
var postTitle = mView.findViewById<TextView>(R.id.post_title)
postTitle?.text = title
}
fun setDes(des:String){
var postDes = mView.findViewById<TextView>(R.id.post_des)
postDes?.text = des
}
fun setImage(image:String){
var postImage = mView.findViewById<ImageView>(R.id.post_title)
Picasso.get().load(image).into(postImage)
}
}
}
If you apply kotlin-android-extensions plugin then you don't need to use findViewById anymore because you can access views in the layout as if they're properties (by name). So, your onCreate could look as follows:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
assert recyclee != null
}
Edit
Since you're trying to do this in Fragment and your layout file is called
fragment_List.xml then in your Fragment you must inflate the layout first and then you can access your RecyclerView as in the example above for Activity:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_List, container, false)
}
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
assert recyclee != null
}
If you try to access your RecyclerView in Activity before fragment_List is inflated in the Fragment then it will obviously be null (it hasn't been created yet). That's actually what you're trying to do in onCreate - it's too early as the Fragment's layout hasn't been built yet.
Edit 2
As it's seen from your code, mBlogList = recyclee is set in onCreate. Even though it's done after the ListFragment is created, it's still too early as its onCreateView hasn't been called yet and so no layout is in place.
A quick fix would be to do it in onStart as at that point ListFragment is definitely there. However, a better approach is to do the logic inside ListFragment itself and communicate with MainActivity via callbacks as described here
Try to use the findViewById on onCreate or onCreateView (if you are in a Fragment). It is happening because before this methods your layout wasn't inflated yet so Android cannot find your RecyclerView
class MainActivity : AppCompatActivity() {
private lateinit var mBlogList : RecyclerView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mBlogList = findViewById<RecyclerView>(R.id.recyclee)
}
}
I would recommend you to read this: https://kotlinlang.org/docs/tutorials/android-plugin.html
Kotlin has a better way to get the reference os your views, you don't need to use findViewById =)
You cannot call findViewById from the global scope. But, you can declare it as:
private val mBlogList by lazy { findViewById<RecyclerView>(R.id.recyclee) }
...then use the variable the usual.
In this way you could access RecyclerView attributes once adapter has been loaded at onCreate() function
var recyclerView : RecyclerViewAdapterYourClass = adapter as RecyclerViewAdapterYourClass
recyclerView.yourRecyclerAttribute

Categories

Resources