Возможно ли получить `RecyclerView` из фрагмента?
Пытаясь получить RecyclerView
из этого макета:
<?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>
в основной класс деятельности:
private var mBlogList = findViewById<RecyclerView>(R.id.recyclee)
получить ошибку:java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.Window$Callback android.view.Window.getCallback()' on a null object reference
любая помощь, пожалуйста:)
редактировать 1
сейчас я использую расширение kotlin
import kotlinx.android.synthetic.main.fragment_list.*
class MainActivity : AppCompatActivity() {
private lateinit var mBlogList : RecyclerView
в методе onCreate:
mBlogList = recyclee
но та же ошибка все еще существует
редактировать 2 listFragment код:
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()
}
}
отредактируйте 3 всего кода MainActivity:
//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)
}
}
}
4 ответа
Если вы подаете заявку kotlin-android-extensions
плагин, то вам не нужно использовать findViewById
больше, потому что вы можете получить доступ к представлениям в макете, как если бы они были свойствами (по имени). Так что ваши onCreate
может выглядеть следующим образом:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
assert recyclee != null
}
редактировать
Так как вы пытаетесь сделать это в Fragment
и ваш файл макета называется fragment_List.xml
тогда в вашем Fragment
сначала вы должны надуть макет, а затем вы можете получить доступ к RecyclerView
как в примере выше для 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
}
Если вы попытаетесь получить доступ к вашему RecyclerView
в Activity
до fragment_List
раздувается в Fragment
тогда это будет очевидно null
(он еще не был создан). Это на самом деле то, что вы пытаетесь сделать в onCreate
- слишком рано Fragment's
макет еще не построен.
Редактировать 2
Как видно из вашего кода, mBlogList = recyclee
установлен в onCreate
, Хотя это сделано после ListFragment
еще слишком рано onCreateView
еще не был вызван, и поэтому нет макета на месте.
Быстрое решение было бы сделать это в onStart
как в тот момент ListFragment
определенно там. Тем не менее, лучший подход заключается в том, чтобы сделать логику внутри ListFragment
сам и общаюсь с MainActivity
через обратные вызовы, как описано здесь
Попробуйте использовать findViewById
onCreate или OnCreateView (если вы во фрагменте). Это происходит потому, что до этого методы ваш макет еще не был раздут, поэтому Android не может найти ваш 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)
}
}
Я бы порекомендовал вам прочитать это: https://kotlinlang.org/docs/tutorials/android-plugin.html Kotlin есть лучший способ получить ссылку на ваши взгляды, вам не нужно использовать findViewById
знак равно
Вы не можете позвонить findViewById
из глобальной сферы. Но вы можете объявить это как:
private val mBlogList by lazy { findViewById<RecyclerView>(R.id.recyclee) }
... тогда используйте переменную как обычно.
Таким образом, вы могли получить доступ
RecyclerView
атрибуты после загрузки адаптера в
onCreate()
функция
var recyclerView : RecyclerViewAdapterYourClass = adapter as RecyclerViewAdapterYourClass
recyclerView.yourRecyclerAttribute