我有一个应用,可显示MainActivity
中片段的产品列表。使用ViewModel
通过Repository
从Firestore数据库中读取项目列表。
MainActivtiy:
class MainActivity : AppCompatActivity() {
private val model: ProductViewModel by lazy {
ViewModelProvider(this).get(ProductViewModel::class.java)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
supportFragmentManager.beginTransaction().replace(R.id.fragment, ProductListFragment())
.commit()
...
ProductListFragment:
class ProductListFragment : Fragment() {
private val model: ProductViewModel by lazy {
ViewModelProvider(activity as ViewModelStoreOwner).get(ProductViewModel::class.java)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val listView =
inflater.inflate(R.layout.product_list_fragment, container, false) as RecyclerView
listView.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
model.products.observe(viewLifecycleOwner, Observer { productList ->
listView.adapter = ProductListAdapter(productList) // THIS LINE IS PART OF THE ERROR
})
return listView
}
private fun selectItem(product: Product) {
model.select(product)
fragmentManager?.beginTransaction()?.replace(R.id.fragment, ProductDetailsFragment())
?.commit()
}
private inner class ProductListAdapter(var productList: List<Product>) :
RecyclerView.Adapter<ProductListAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.product_list_item, parent, false)
return ViewHolder(view)
}
override fun getItemCount(): Int {
return productList.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val product = productList[position]
holder.productName.text = product.title
holder.itemView.setOnClickListener {
selectItem(product)
}
}
private inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val productName: TextView = view.findViewById(R.id.productName)
}
}
}
ProductViewModel.kt:
class ProductViewModel : ViewModel() {
val products: LiveData<List<Product>> by lazy {
MutableLiveData<List<Product>>().also {
val productList = arrayListOf<Product>()
Repository.getAllProducts()?.addOnSuccessListener {products ->
products.forEach { product ->
productList.add(product.toObject(Product::class.java))
}
it.value = productList // THIS LINE IS CAUSING AN ERROR
}
}
}
...
Repository.kt:
object Repository {
private val db = FirebaseFirestore.getInstance()
private val productCollection: CollectionReference?
get() {
val user = Authenticator.user
if (user != null) {
return db.collection(USERS).document(user.uid).collection(COLLECTION)
}
return null
}
fun getAllProducts(): Task<QuerySnapshot>? {
return productCollection?.get()
}
...
这是我得到的错误:
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean androidx.recyclerview.widget.RecyclerView$ViewHolder.shouldIgnore()' on a null object reference
at androidx.recyclerview.widget.RecyclerView$LayoutManager.removeAndRecycleAllViews(RecyclerView.java:10340)
at androidx.recyclerview.widget.RecyclerView.removeAndRecycleViews(RecyclerView.java:1179)
at androidx.recyclerview.widget.RecyclerView.setAdapterInternal(RecyclerView.java:1202)
at androidx.recyclerview.widget.RecyclerView.setAdapter(RecyclerView.java:1161)
at .ProductListFragment$onCreateView$1.onChanged(ProductListFragment.kt:35)
at .ProductListFragment$onCreateView$1.onChanged(ProductListFragment.kt:22)
at androidx.lifecycle.LiveData.considerNotify(LiveData.java:131)
at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:149)
at androidx.lifecycle.LiveData.setValue(LiveData.java:307)
at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:50)
at .ProductViewModel$products$2$1$1.onSuccess(ProductViewModel.kt:17)
at .ProductViewModel$products$2$1$1.onSuccess(ProductViewModel.kt:9)
at com.google.android.gms.tasks.zzn.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6682)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
数据库具有该集合的三个条目,但是存储库传递给onSuccess
函数的值是一个空列表(不是null
)。我在这里有两个问题:
viemodel
和recyclerview
而不是onViewCreated
中的onCreateView
调用>
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) //view model and recyclerview }
//活动!
ViewModelProvider(activity!!.get(ProductViewModel::class.java)