Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Synthetic import in kotlin not working

Tags:

android

kotlin

In a Fragment, Kotlins synthetic import for layouts provided by Anko isn't working. I am trying to set the visibility of the views but it says the view is null. I have the following code.

class HistoryFragment : Fragment(), HistoryContract.view, LoaderManager.LoaderCallbacks<List<SongEntity>>{

    private lateinit var mPresenter : HistoryContract.Presenter
    private lateinit var adapter: HistoryAdapte
    private val loaderId : Int = 101

    override fun onLoadFinished(loader: Loader<List<SongEntity>>?, data: List<SongEntity>?) {
        hideLoadingIndicator()

        if (data == null) {
            showErrorView()
        } else {
            //update the adapter
            adapter.updateDataset(data)
        }
    }

    override fun onLoaderReset(loader: Loader<List<SongEntity>>?) {
    }

    override fun onCreateLoader(id: Int, args: Bundle?): Loader<List<SongEntity>> {
       showLoadingIndicator()

       return object : AsyncTaskLoader<List<SongEntity>>(activity!!.baseContext){
            override fun loadInBackground(): List<SongEntity>? {
                return mPresenter.fetchSongs()
            }
        }
    }

    override fun showLoadingIndicator() {
        song_history_pv.visibility = View.VISIBLE
    }

    override fun hideLoadingIndicator() {
        song_history_pv.visibility = View.INVISIBLE
    }

    override fun showErrorView() {
        song_history_error_tv.visibility = View.VISIBLE
    }

    override fun hideErrorView() {
        song_history_error_tv.visibility = View.INVISIBLE
    }

    override fun setPresenter(presenter: HistoryContract.Presenter) {
        mPresenter = presenter
    }

    override fun showDiscoveredSongs(songs: List<SongEntity>) {
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        val rootView = inflater.inflate(R.layout.fragment_song_history, container, false)
        loaderManager.initLoader(loaderId, null , this)
        songHistoryRv.layoutManager = LinearLayoutManager(context)
        songHistoryRv.adapter = HistoryAdapter {
            Toast.makeText(activity!!.baseContext, "${it.name}", Toast.LENGTH_SHORT).show()
        }

        return rootView
    }
}

Now when I am setting the visibility of the progress view in the showLoadingIndicator function i am getting the error that the view is null.

This is the null error I am getting

Below is the layout file that I am using for the fragment

    <?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/songHistoryRv"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <ProgressBar
        android:id="@+id/song_history_pv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <TextView
        android:id="@+id/song_history_error_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/song_history_error"
        android:visibility="invisible"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"/>

</android.support.constraint.ConstraintLayout>

import kotlinx.android.synthetic.main.fragment_song_history.* is the synthetic import that I am using.

Please help me out on this. Am I missing something? I am new to kotlin.

like image 211
nick.tdr Avatar asked Nov 24 '25 10:11

nick.tdr


1 Answers

Your issue is that you are trying to access the view too early. In #onCreateView you are inflating your view but Fragment#getView() will still return null as long as you do not return the inflated view. Internally the Kotlin Android Extensions use getView().findViewById(int) method to bind the views the first time you are trying to access it.

tl;dr

To fix your issue simply return the inflated view in #onCreateView and move your operations regarding the LoaderManager to #onViewCreated:

class HistoryFragment : Fragment(), HistoryContract.view, LoaderManager.LoaderCallbacks<List<SongEntity>>{

    // ...

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        return inflater.inflate(R.layout.fragment_song_history, container, false)
    }

    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
        loaderManager.initLoader(loaderId, null , this)
        songHistoryRv.layoutManager = LinearLayoutManager(context)
        songHistoryRv.adapter = HistoryAdapter {
            Toast.makeText(activity!!.baseContext, "${it.name}", Toast.LENGTH_SHORT).show()
        }
    }

}
like image 142
reVerse Avatar answered Nov 26 '25 23:11

reVerse



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!