片段未附加到上下文
Fragment is not attached to a context
我打算在名为“FazendaListFragment”的片段中显示先前在数据库 (SQLite) 中注册的农场 (Fazendas) 列表,该片段是 FazendaActivity 的一部分。这里我有两个屏幕使用 ViewPage 通过滑动进行屏幕更改,但我在这个问题的标题中报告了问题。我不知道如何使用附加上下文解决这个问题。代码如下:
Fazenda活动
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_fazenda)
setupTabs()
}
private fun setupTabs(){
val adapter = ViewPagerAdapter(supportFragmentManager)
adapter.addFragment(FazendaListFragment(), "")
adapter.addFragment(ListaPastoFragment(), "")
view_pager_fazenda.adapter = adapter
tabs.setupWithViewPager(view_pager_fazenda)
tabs.getTabAt(0)!!.setIcon(R.drawable.ic_baseline_foundation_24)
tabs.getTabAt(1)!!.setIcon(R.drawable.ic_outline_fence_24)
}
FazendaListFragment (已更新)
ar nameList = ArrayList<String>()
//Iniciando RecyclerView
var fazendaAdapter: FazendaListAdapter? = null
var linearLayoutManager: LinearLayoutManager? = null
//Iniciando o SQLite
var fazendaList = ArrayList<Fazenda>()
val fazendaDatabaseHandler by lazy { FazendaDatabaseHandler(requireContext()) }
private var cadastroFazenda: FloatingActionButton? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_lista_fazenda, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initView()
}
private fun deleteAdapter(position: Int){
fazendaList.removeAt(position)
fazendaAdapter!!.notifyItemRemoved(position)
}
private fun initView() {
fazendaList = fazendaDatabaseHandler.fazendas()
fazendaAdapter = FazendaListAdapter(fazendaList, requireContext(), this::deleteAdapter)
linearLayoutManager = LinearLayoutManager(context)
recyclerview.layoutManager = linearLayoutManager
recyclerview.adapter = fazendaAdapter
}
FazendaListAdapter
internal var fazendaList: List<Fazenda> = ArrayList<Fazenda>()
init{
this.fazendaList = fazendaList
}
//Aqui é onde o ViewHolder é criado a partir do layout
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(context).inflate(R.layout.content_fazenda_list, parent, true)
return ViewHolder(view)
}
//Nessa parte é onde se modifica o item do ViewHolder
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val fazenda = fazendaList[position]
holder.name.text = fazenda.nome
holder.cnpj.text = fazenda.cnpj
holder.endereco.text = fazenda.endereco
holder.editbtn.setOnClickListener{
val intent = Intent(context, CadastroFazendaActivity::class.java)
intent.putExtra("edit", true)
intent.putExtra("position", fazenda.id)
context.startActivity(intent)
}
holder.delbtn.setOnClickListener{
val view = View.inflate(context, R.layout.dialog_confirm_delete_fazenda, null)
val builder = AlertDialog.Builder(context)
builder.setView(view)
val dialog = builder.create()
dialog.show()
dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
view.btn_delete.setOnClickListener {
val fazendaDatabaseHandler = FazendaDatabaseHandler(context)
fazendaDatabaseHandler.deleteFazenda(fazenda.id)
callbacks(position)
dialog.dismiss()
}
}
}
//Devolve a quantidade de itens do fazendaList
override fun getItemCount(): Int {
return fazendaList.size
}
//Aqui é a criação dos itens do ViewHolder
inner class ViewHolder(view: View): RecyclerView.ViewHolder(view){
var name: TextView = view.tvAdpNome
var cnpj: TextView = view.tvAdpCNPJ
var endereco: TextView = view.tvAdpEndereco
var delbtn: Button = view.deleteButton
var editbtn: Button = view.editButton
}
ViewPagerAdapter
private val mFragmentList = ArrayList<Fragment>()
private val mFragmentTitleList = ArrayList<String>()
override fun getItem(position: Int): Fragment {
return mFragmentList[position]
}
override fun getCount(): Int {
return mFragmentList.size
}
override fun getPageTitle(position: Int): CharSequence? {
return mFragmentTitleList[position]
}
fun addFragment(fragment: Fragment, title: String){
mFragmentList.add(fragment)
mFragmentTitleList.add(title)
}
错误日志在这里:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: br.com.appintellipec, PID: 6685
java.lang.RuntimeException: Unable to start activity ComponentInfo{br.com.appintellipec/br.com.appintellipec.FazendaActivity}: java.lang.IllegalStateException: Fragment FazendaListFragment{524ae27} (f65a2c7c-2524-45f7-908a-12db24890acc) not attached to a context.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: java.lang.IllegalStateException: Fragment FazendaListFragment{524ae27} (f65a2c7c-2524-45f7-908a-12db24890acc) not attached to a context.
at androidx.fragment.app.Fragment.requireContext(Fragment.java:900)
at br.com.appintellipec.fragments.FazendaListFragment.<init>(FazendaListFragment.kt:32)
at br.com.appintellipec.FazendaActivity.setupTabs(FazendaActivity.kt:22)
at br.com.appintellipec.FazendaActivity.onCreate(FazendaActivity.kt:17)
at android.app.Activity.performCreate(Activity.java:8000)
at android.app.Activity.performCreate(Activity.java:7984)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
您应该只为方法 initView()
初始化一次。它是 onCreateView
或 onResume
.
接下来,您应该使用 requiredContext()
而不是 context
。
fazendaAdapter = FazendaListAdapter(fazendaList, requiredContext(), this::deleteAdapter)
更新:
您似乎没有为该视图实现。所有的视图都应该在return里面onCreateView
。看来你return早了。
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_lista_fazenda, container, false)
initView()
return view //This one need at the last
}
override fun onResume() {
super.onResume()
//initView() //comment this one. you just need to implement one only
}
您不能在 属性 初始化站点调用 requireContext()
,因为属性是在 Fragment 实例仍在构建时初始化的,这是在它可能附加到上下文之前。这行有你的错误:
var fazendaDatabaseHandler = FazendaDatabaseHandler(requireContext())
您可以延迟加载它,因此它只会在您第一次使用 属性:
时调用 requireContext()
val fazendaDatabaseHandler by lazy { FazendaDatabaseHandler(requireContext()) }
或者您可以将其设为 lateinit var
并在 onViewCreated()
中对其进行初始化,届时可以安全地调用 requireContext()
:
lateinit var fazendaDatabaseHandler: FazendaDatabaseHandler
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
fazendaDatabaseHandler = FazendaDatabaseHandler(requireContext())
//...
}
我打算在名为“FazendaListFragment”的片段中显示先前在数据库 (SQLite) 中注册的农场 (Fazendas) 列表,该片段是 FazendaActivity 的一部分。这里我有两个屏幕使用 ViewPage 通过滑动进行屏幕更改,但我在这个问题的标题中报告了问题。我不知道如何使用附加上下文解决这个问题。代码如下:
Fazenda活动
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_fazenda)
setupTabs()
}
private fun setupTabs(){
val adapter = ViewPagerAdapter(supportFragmentManager)
adapter.addFragment(FazendaListFragment(), "")
adapter.addFragment(ListaPastoFragment(), "")
view_pager_fazenda.adapter = adapter
tabs.setupWithViewPager(view_pager_fazenda)
tabs.getTabAt(0)!!.setIcon(R.drawable.ic_baseline_foundation_24)
tabs.getTabAt(1)!!.setIcon(R.drawable.ic_outline_fence_24)
}
FazendaListFragment (已更新)
ar nameList = ArrayList<String>()
//Iniciando RecyclerView
var fazendaAdapter: FazendaListAdapter? = null
var linearLayoutManager: LinearLayoutManager? = null
//Iniciando o SQLite
var fazendaList = ArrayList<Fazenda>()
val fazendaDatabaseHandler by lazy { FazendaDatabaseHandler(requireContext()) }
private var cadastroFazenda: FloatingActionButton? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_lista_fazenda, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initView()
}
private fun deleteAdapter(position: Int){
fazendaList.removeAt(position)
fazendaAdapter!!.notifyItemRemoved(position)
}
private fun initView() {
fazendaList = fazendaDatabaseHandler.fazendas()
fazendaAdapter = FazendaListAdapter(fazendaList, requireContext(), this::deleteAdapter)
linearLayoutManager = LinearLayoutManager(context)
recyclerview.layoutManager = linearLayoutManager
recyclerview.adapter = fazendaAdapter
}
FazendaListAdapter
internal var fazendaList: List<Fazenda> = ArrayList<Fazenda>()
init{
this.fazendaList = fazendaList
}
//Aqui é onde o ViewHolder é criado a partir do layout
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(context).inflate(R.layout.content_fazenda_list, parent, true)
return ViewHolder(view)
}
//Nessa parte é onde se modifica o item do ViewHolder
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val fazenda = fazendaList[position]
holder.name.text = fazenda.nome
holder.cnpj.text = fazenda.cnpj
holder.endereco.text = fazenda.endereco
holder.editbtn.setOnClickListener{
val intent = Intent(context, CadastroFazendaActivity::class.java)
intent.putExtra("edit", true)
intent.putExtra("position", fazenda.id)
context.startActivity(intent)
}
holder.delbtn.setOnClickListener{
val view = View.inflate(context, R.layout.dialog_confirm_delete_fazenda, null)
val builder = AlertDialog.Builder(context)
builder.setView(view)
val dialog = builder.create()
dialog.show()
dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
view.btn_delete.setOnClickListener {
val fazendaDatabaseHandler = FazendaDatabaseHandler(context)
fazendaDatabaseHandler.deleteFazenda(fazenda.id)
callbacks(position)
dialog.dismiss()
}
}
}
//Devolve a quantidade de itens do fazendaList
override fun getItemCount(): Int {
return fazendaList.size
}
//Aqui é a criação dos itens do ViewHolder
inner class ViewHolder(view: View): RecyclerView.ViewHolder(view){
var name: TextView = view.tvAdpNome
var cnpj: TextView = view.tvAdpCNPJ
var endereco: TextView = view.tvAdpEndereco
var delbtn: Button = view.deleteButton
var editbtn: Button = view.editButton
}
ViewPagerAdapter
private val mFragmentList = ArrayList<Fragment>()
private val mFragmentTitleList = ArrayList<String>()
override fun getItem(position: Int): Fragment {
return mFragmentList[position]
}
override fun getCount(): Int {
return mFragmentList.size
}
override fun getPageTitle(position: Int): CharSequence? {
return mFragmentTitleList[position]
}
fun addFragment(fragment: Fragment, title: String){
mFragmentList.add(fragment)
mFragmentTitleList.add(title)
}
错误日志在这里:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: br.com.appintellipec, PID: 6685
java.lang.RuntimeException: Unable to start activity ComponentInfo{br.com.appintellipec/br.com.appintellipec.FazendaActivity}: java.lang.IllegalStateException: Fragment FazendaListFragment{524ae27} (f65a2c7c-2524-45f7-908a-12db24890acc) not attached to a context.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: java.lang.IllegalStateException: Fragment FazendaListFragment{524ae27} (f65a2c7c-2524-45f7-908a-12db24890acc) not attached to a context.
at androidx.fragment.app.Fragment.requireContext(Fragment.java:900)
at br.com.appintellipec.fragments.FazendaListFragment.<init>(FazendaListFragment.kt:32)
at br.com.appintellipec.FazendaActivity.setupTabs(FazendaActivity.kt:22)
at br.com.appintellipec.FazendaActivity.onCreate(FazendaActivity.kt:17)
at android.app.Activity.performCreate(Activity.java:8000)
at android.app.Activity.performCreate(Activity.java:7984)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
您应该只为方法 initView()
初始化一次。它是 onCreateView
或 onResume
.
接下来,您应该使用 requiredContext()
而不是 context
。
fazendaAdapter = FazendaListAdapter(fazendaList, requiredContext(), this::deleteAdapter)
更新:
您似乎没有为该视图实现。所有的视图都应该在return里面onCreateView
。看来你return早了。
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_lista_fazenda, container, false)
initView()
return view //This one need at the last
}
override fun onResume() {
super.onResume()
//initView() //comment this one. you just need to implement one only
}
您不能在 属性 初始化站点调用 requireContext()
,因为属性是在 Fragment 实例仍在构建时初始化的,这是在它可能附加到上下文之前。这行有你的错误:
var fazendaDatabaseHandler = FazendaDatabaseHandler(requireContext())
您可以延迟加载它,因此它只会在您第一次使用 属性:
时调用requireContext()
val fazendaDatabaseHandler by lazy { FazendaDatabaseHandler(requireContext()) }
或者您可以将其设为 lateinit var
并在 onViewCreated()
中对其进行初始化,届时可以安全地调用 requireContext()
:
lateinit var fazendaDatabaseHandler: FazendaDatabaseHandler
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
fazendaDatabaseHandler = FazendaDatabaseHandler(requireContext())
//...
}