是否有可能从片段中获取“RecyclerView”?
is it possible to get `RecyclerView` from Fragment?
尝试从此布局中获取 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>
进入主activity class :
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
列表片段代码:
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)
}
}
}
尝试在 onCreate 或 onCreateView 上使用 findViewById
(如果您在 Fragment 中)。发生这种情况是因为在此方法之前您的布局尚未膨胀,因此 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 有更好的方法来获取参考 os 你的观点,你不需要使用 findViewById
=)
您不能从全局范围调用 findViewById
。但是,您可以将其声明为:
private val mBlogList by lazy { findViewById<RecyclerView>(R.id.recyclee) }
...然后使用通常的变量。
如果您应用 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
}
如果您在 fragment_List
在 Fragment
中膨胀之前尝试在 Activity
中访问您的 RecyclerView
那么它显然是 null
(它没有'尚未创建)。这实际上就是您在 onCreate
中尝试做的事情 - 因为 Fragment's
布局尚未构建,所以现在还为时过早。
编辑 2
从你的代码可以看出,mBlogList = recyclee
设置在onCreate
中。尽管它是在创建 ListFragment
之后完成的,但还为时过早,因为它的 onCreateView
尚未被调用,因此还没有布局到位。
一个快速的解决方法是在 onStart
中执行此操作,因为此时 ListFragment
肯定存在。 但是,更好的方法是在 ListFragment
内部执行逻辑并通过回调与 MainActivity
通信,如 here
所述
通过这种方式,一旦在 onCreate()
函数
处加载了适配器,您就可以访问 RecyclerView
属性
var recyclerView : RecyclerViewAdapterYourClass = adapter as RecyclerViewAdapterYourClass
recyclerView.yourRecyclerAttribute
尝试从此布局中获取 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>
进入主activity class :
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 列表片段代码:
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)
}
}
}
尝试在 onCreate 或 onCreateView 上使用 findViewById
(如果您在 Fragment 中)。发生这种情况是因为在此方法之前您的布局尚未膨胀,因此 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 有更好的方法来获取参考 os 你的观点,你不需要使用 findViewById
=)
您不能从全局范围调用 findViewById
。但是,您可以将其声明为:
private val mBlogList by lazy { findViewById<RecyclerView>(R.id.recyclee) }
...然后使用通常的变量。
如果您应用 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
}
如果您在 fragment_List
在 Fragment
中膨胀之前尝试在 Activity
中访问您的 RecyclerView
那么它显然是 null
(它没有'尚未创建)。这实际上就是您在 onCreate
中尝试做的事情 - 因为 Fragment's
布局尚未构建,所以现在还为时过早。
编辑 2
从你的代码可以看出,mBlogList = recyclee
设置在onCreate
中。尽管它是在创建 ListFragment
之后完成的,但还为时过早,因为它的 onCreateView
尚未被调用,因此还没有布局到位。
一个快速的解决方法是在 onStart
中执行此操作,因为此时 ListFragment
肯定存在。 但是,更好的方法是在 ListFragment
内部执行逻辑并通过回调与 MainActivity
通信,如 here
通过这种方式,一旦在 onCreate()
函数
RecyclerView
属性
var recyclerView : RecyclerViewAdapterYourClass = adapter as RecyclerViewAdapterYourClass
recyclerView.yourRecyclerAttribute