Android 带有RecyclerView的房间数据库视图
我是Room和Kotlin的新手,我正在尝试构建一个简单的Room数据库,并将其显示在ViewPager中的RecyclerView中 该活动包含一个ViewPager对象,该ViewPager包含一个片段,该片段包含一个RecyclerView: 活动-->查看页面-->片段-->回收视图 我遇到的问题是,当我尝试接收数据库时(在插入之后),我得到了null 代码: 道: 活动:Android 带有RecyclerView的房间数据库视图,android,database,kotlin,android-room,Android,Database,Kotlin,Android Room,我是Room和Kotlin的新手,我正在尝试构建一个简单的Room数据库,并将其显示在ViewPager中的RecyclerView中 该活动包含一个ViewPager对象,该ViewPager包含一个片段,该片段包含一个RecyclerView: 活动-->查看页面-->片段-->回收视图 我遇到的问题是,当我尝试接收数据库时(在插入之后),我得到了null 代码: 道: 活动: class EventActivity : AppCompatActivity() { private l
class EventActivity : AppCompatActivity()
{
private lateinit var viewPager: ViewPager
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_event)
viewPager = findViewById(R.id.guests_view_pager)
val pagerAdapter = EventPagerAdapter(supportFragmentManager)
viewPager.adapter = pagerAdapter
}
}
适配器:
class EventPagerAdapter(fragmentManager: FragmentManager): FragmentPagerAdapter(fragmentManager)
{
override fun getCount(): Int
{
return 1
}
override fun getItem(position: Int): Fragment
{
return GuestListFragment.newInstance()
}
}
片段:
class GuestListFragment : Fragment()
{
private var guestsDataBase: InviterRoomDatabase? = null
private lateinit var dbWorkerThread: DBWorkerThread
companion object
{
fun newInstance(): GuestListFragment
{
val fragment = GuestListFragment()
return fragment
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
{
dbWorkerThread = DBWorkerThread("workerThread")
dbWorkerThread.start()
guestsDataBase = InviterRoomDatabase.getDatabase(this.context!!)
insertGuestToDB(Guest("Joe","052352332",false,0))
var rootView = inflater.inflate(R.layout.fragment_guest_list, container, false)
var rv: RecyclerView = rootView.findViewById(R.id.guests_list_recycler_view)
rv.layoutManager = LinearLayoutManager(context)
var d = getAllDataFromDB()
rv.adapter = GuestsRecycleViewAdapter.newInstance(d)
return rootView
}
private fun insertGuestToDB(guest: Guest)
{
val task = Runnable {guestsDataBase?.guestsDao()?.insert(guest)}
dbWorkerThread.postTask(task)
}
private fun getAllDataFromDB(): List<Guest>
{
var data: List<Guest> = emptyList()
val task = Runnable { data = guestsDataBase?.guestsDao()?.getAllGuests()!!}
dbWorkerThread.postTask(task)
return data
}
}
class GuestListFragment:Fragment()
{
私有var guestsDataBase:InviterRoomDatabase?=null
私有lateinit var dbWorkerThread:dbWorkerThread
伴星
{
fun newInstance():GuestListFragment
{
val fragment=GuestListFragment()
返回片段
}
}
覆盖创建视图(充气机:布局充气机,容器:ViewGroup?,savedInstanceState:Bundle?):视图?
{
dbWorkerThread=dbWorkerThread(“workerThread”)
dbWorkerThread.start()
guestsDataBase=InviterRoomDatabase.getDatabase(this.context!!)
插入GuestToDB(Guest(“Joe”,“052352332”,假,0))
var rootView=充气机。充气(R.layout.fragment\u guest\u列表,容器,false)
var rv:RecyclerView=rootView.findviewbyd(R.id.guests\u list\u recycler\u视图)
rv.layoutManager=LinearLayoutManager(上下文)
var d=getAllDataFromDB()
rv.adapter=GuestsRecycleViewAdapter.newInstance(d)
返回根视图
}
私人娱乐insertGuestToDB(客人:客人)
{
val task=Runnable{guestsDataBase?.guestsDao()?.insert(guest)}
dbWorkerThread.postTask(任务)
}
private fun getAllDataFromDB():列表
{
变量数据:List=emptyList()
val task=Runnable{data=guestsDataBase?.guestsDao()?.getAllGuests()!!}
dbWorkerThread.postTask(任务)
返回数据
}
}
您需要理解多线程的概念,才能理解代码无法工作的原因。简而言之,您得到的是一个空列表,因为您试图在主线程中获得该列表,而在工作线程上运行的插入和查询尚未完成
我将注释放在代码中以解释执行顺序。注释中的编号为完成顺序:
请注意,这绝对不是解决此问题的最佳方法。这是一个非常常见的问题,有很多不同的解决方案更具可读性、灵活性和可维护性。只是其他解决方案需要更深入的理解,多线程是一个如此广泛的主题,我无法用一个简单的答案解释所有这些问题。不过,我希望您能了解总体思路,并鼓励您探索解决此问题的其他解决方案。您确定数据库为空吗?当您在INSERT和get函数中使用线程时,可能会得到一个null,因为当您尝试从数据库获取数据时,数据尚未添加..我尝试单独插入并获取所有数据,但我还是得到了空列表对于这种情况,什么是最好的方法?@Itay我想说,使用或的反应式设计可以说是最先进的解决方案。你可能已经很熟悉了。似乎有更多的
Android-room
教程使用其中一个,而不是没有它们的教程。
class EventActivity : AppCompatActivity()
{
private lateinit var viewPager: ViewPager
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_event)
viewPager = findViewById(R.id.guests_view_pager)
val pagerAdapter = EventPagerAdapter(supportFragmentManager)
viewPager.adapter = pagerAdapter
}
}
class EventPagerAdapter(fragmentManager: FragmentManager): FragmentPagerAdapter(fragmentManager)
{
override fun getCount(): Int
{
return 1
}
override fun getItem(position: Int): Fragment
{
return GuestListFragment.newInstance()
}
}
class GuestListFragment : Fragment()
{
private var guestsDataBase: InviterRoomDatabase? = null
private lateinit var dbWorkerThread: DBWorkerThread
companion object
{
fun newInstance(): GuestListFragment
{
val fragment = GuestListFragment()
return fragment
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
{
dbWorkerThread = DBWorkerThread("workerThread")
dbWorkerThread.start()
guestsDataBase = InviterRoomDatabase.getDatabase(this.context!!)
insertGuestToDB(Guest("Joe","052352332",false,0))
var rootView = inflater.inflate(R.layout.fragment_guest_list, container, false)
var rv: RecyclerView = rootView.findViewById(R.id.guests_list_recycler_view)
rv.layoutManager = LinearLayoutManager(context)
var d = getAllDataFromDB()
rv.adapter = GuestsRecycleViewAdapter.newInstance(d)
return rootView
}
private fun insertGuestToDB(guest: Guest)
{
val task = Runnable {guestsDataBase?.guestsDao()?.insert(guest)}
dbWorkerThread.postTask(task)
}
private fun getAllDataFromDB(): List<Guest>
{
var data: List<Guest> = emptyList()
val task = Runnable { data = guestsDataBase?.guestsDao()?.getAllGuests()!!}
dbWorkerThread.postTask(task)
return data
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
{
// [1] onCreateView starts on main thread.
dbWorkerThread = DBWorkerThread("workerThread")
dbWorkerThread.start()
guestsDataBase = InviterRoomDatabase.getDatabase(this.context!!)
// [2] calls insertGuestToDB on main thread.
insertGuestToDB(Guest("Joe","052352332",false,0))
var rootView = inflater.inflate(R.layout.fragment_guest_list, container, false)
var rv: RecyclerView = rootView.findViewById(R.id.guests_list_recycler_view)
rv.layoutManager = LinearLayoutManager(context)
// [4] calls getAllDataFromDB on main thread.
var d = getAllDataFromDB()
// [6] get "d" on main thread. "d" is an empty list.
rv.adapter = GuestsRecycleViewAdapter.newInstance(d)
return rootView
}
private fun insertGuestToDB(guest: Guest)
{
// [2] insertGuestToDB executed on main thread.
val task = Runnable {
guestsDataBase?.guestsDao()?.insert(guest)
// [7] insertion finished on worker thread.
}
dbWorkerThread.postTask(task)
// [3] insertGuestToDB finishes on main thread.
}
private fun getAllDataFromDB(): List<Guest>
{
// [4] getAllDataFromDB on main thread. "data" points to an empty list
var data: List<Guest> = emptyList()
val task = Runnable {
data = guestsDataBase?.guestsDao()?.getAllGuests()!!
// [8] query finishes on worker thread, but "data" is now lost.
}
dbWorkerThread.postTask(task)
// [5] returns on main thread. "data" still points to an empty list
return data
}
var rv: RecyclerView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
{
dbWorkerThread = DBWorkerThread("workerThread")
dbWorkerThread.start()
var rootView = inflater.inflate(R.layout.fragment_guest_list, container, false)
rv= rootView.findViewById(R.id.guests_list_recycler_view)
rv.layoutManager = LinearLayoutManager(context)
guestsDataBase = InviterRoomDatabase.getDatabase(this.context!!)
insertGuestToDbAndUpdateRv(Guest("Joe","052352332",false,0))
return rootView
}
private fun insertGuestToDbAndUpdateRv(guest: Guest)
{
val task = Runnable {
// 1. Insert on a worker thread.
guestsDataBase?.guestsDao()?.insert(guest)
// 2. Query on a worker thread.
var data = guestsDataBase?.guestsDao()?.getAllGuests()!!
this@GuestListFragment.getActivity().runOnUiThread {
// 3. Once they are done, update ui on main thread.
rv.adapter = GuestsRecycleViewAdapter.newInstance(data)
}
}
dbWorkerThread.postTask(task)
}