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