Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IllegalStateException: RecyclerView is null inside of Fragment within NavigationDrawer activity

I tried to make a RecyclerView that will go inside one of the two pages of my fragments. These pages are put inside a NavigationDrawer activity. The goal is to create something like the Play Store app homepage.

But I found an error in this snippet of code on runtime. It says:

java.lang.IllegalStateException: mainMenu must not be null
    at com.example.MyApp.app.fragment.MainFragment.onCreate(MainFragment.kt:49)

Ive been looking at some SO threads, and they said that the layouts are not properly loaded. Which caused some elements not linked as it should. Another said in the comments that the problem is with the context not initialized properly. Which is not the case for me (rather it's the RecyclerView).

Here are the links, hope they could be useful as a reference.

  • TextView must not be null
  • context must not be null

After multiple-checks on my codes, I swear I've put the right layouts in. EDIT: I imported the kotlinx.android.synthetic.main.^ package where I put this sign: ^${layout}. Here's some of my files (forgive me if this thread becomes too long):

  • MainActivity.kt : AppCompatActivity() ^activity_main.*

    override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            // preparing the app bars
            setSupportActionBar(toolBar)
    
            // getting ready for the pages
            val pagerAdapter = MainPagerAdapter(
                    supportFragmentManager,
                    resources.getString(R.string.tab_main),
                    resources.getString(R.string.tab_chat)
            )
            pager.adapter = pagerAdapter
    
            // activating tabs
            tabLayout.setupWithViewPager(pager)
    
            val toggle = ActionBarDrawerToggle(
                    this, mainDrawer, toolbar,
                    R.string.navigation_drawer_open,
                    R.string.navigation_drawer_close)
    
            mainDrawer.addDrawerListener(toggle)
    
    
            navView.setNavigationItemSelectedListener(this)
            toggle.syncState()
    
    }
    
  • MainPagerAdapter.kt (fm: FragmentManager, private val page1: String, private val page2: String): FragmentPagerAdapter(fm)

    override fun getItem(position: Int): Fragment? {
        return when (position) {
            0 -> MainFragment()
            1 -> ChatFragment()
            else -> null
        }
    }
    
    override fun getCount() = 2
    
    override fun getPageTitle(position: Int): CharSequence? {
        return when (position) {
            0 -> page1
            1 -> page2
            else -> null
        }
    }
    
  • MainFragment.kt : Fragment() ^content_main.*

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?)
        : View? = inflater.inflate(R.layout.content_main, container)
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        // this is the error
        mainMenu.layoutManager = LinearLayoutManager(this.context)
    
        mainMenu.adapter = MyAdapter(itemList) {
            toast("${it.name} selected")
        }
    }
    
  • MyAdapter.kt: RecyclerView.Adapter<MyAdapter.MyHolder>() ^item_custom.view.*(courtesy of Antonio Leiva)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int)
        = GoodsHolder(parent.inflate(R.layout.item_custom))
    
    override fun getItemCount()
        = itemList.size
    
    override fun onBindViewHolder(holder: MyHolder, position: Int)
        = holder.bind(itemList[position], listener)
    
    
    class MyHolder(v: View): RecyclerView.ViewHolder(v){
        private val item: Item? = null
        private val view = v
    
        fun bind(item: Item, listener: (Item) -> Unit)
                = with (itemView) {
            imgPic.setImageResource(item.pictureId)
            txtName.text = item.name
            txtPrice.text = item.price.toString()
    
        setOnClickListener { listener(item) }
        }
    }
    
  • content_main.xml

    <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"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        tools:context="com.example.MyApp.app.activity.MainActivity"
        >
    
        <!-- the RecyclerView that caused the runtime error -->
        <android.support.v7.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/mainMenu"/>
    
    </android.support.constraint.ConstraintLayout>
    
  • item_custom.xml (These code are inside a LinearLayout inside a CardView)

    <ImageView
        android:id="@+id/imgPic"
        android:layout_width="match_parent"
        android:layout_height="128dp"
        app:srcCompat="@drawable/ic_menu_gallery" />
    
    <TextView
        android:id="@+id/txtName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Get it while it's hot!"
        android:layout_margin="@dimen/margin_small"
        android:layout_marginTop="@dimen/margin_medium"
        android:maxLines="2"
        android:ellipsize="end"
        android:textStyle="bold"
        />
    
    <TextView
        android:id="@+id/txtPrice"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="$3.000.000"
        android:layout_marginLeft="@dimen/margin_small"
        android:layout_marginStart="@dimen/margin_small"
        android:layout_marginRight="@dimen/margin_small"
        android:layout_marginEnd="@dimen/margin_small"
        android:layout_marginBottom="@dimen/margin_medium"/>
    
  • ChatFragment.kt: Fragment() (only contains onCreateView inflating content_main_chat.xml)

  • content_main_chat.xml (only contains a TextView)

like image 987
hdx13_beatcode Avatar asked Jan 26 '18 09:01

hdx13_beatcode


3 Answers

You have not initialized the RecyclerView in MainFragment.kt file. You have to initialize it before the below line:

mainMenu.layoutManager = LinearLayoutManager(this.context)

You can initialize the RecyclerView by the below line:

var mainMenu = findViewById(R.id.mainMenu) as RecyclerView

You have to change it as per your need.

like image 177
Avijit Karmakar Avatar answered Nov 04 '22 11:11

Avijit Karmakar


For anyone that follow the brilliant clue of @Avijit Karmakar, getting in count another discussion, (RecyclerView error: No adapter attached; skipping layout) I had to include :

class WikiFragment : Fragment() {
    val paginas: ArrayList<String> = ArrayList()    

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
var listItems : View  = inflater.inflate(R.layout.fragment_wiki, container, false)

var rv_frag_wiki = listItems.findViewById<View>(R.id.rv_frag_wiki) as RecyclerView


 rv_frag_wiki.layoutManager = LinearLayoutManager(this.context)
        rv_frag_wiki.adapter = PaginasAdapter(paginas, this.context)
        
  return listItems 
  
like image 31
Orthophilos Avatar answered Nov 04 '22 11:11

Orthophilos


Since you are using kotlin you can have advantage of synthetics where you don't need to do var rv_frag_wiki = listItems.findViewById<View>(R.id.rv_frag_wiki) as RecyclerView

Rather import synthetics via plugin Step 1 :

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

Step 2 :

Import sythetic in MainFragment

import kotlinx.android.synthetic.main.content_menu.* //

Step 3 :

Finally in MainFragment

Shift this code of recyclerView here

 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        rvList.layoutManager = LinearLayoutManager(context, 
        LinearLayoutManager.VERTICAL, false)
        rvList.adapter = academyAdapter

    }
like image 36
Kanchan Pal Avatar answered Nov 04 '22 10:11

Kanchan Pal