android– 活动在后台被杀死后应用程序崩溃

android– 活动在后台被杀死后应用程序崩溃,第1张

概述我有一个使用ViewPager显示片段的应用程序的问题.一切正常,直到应用程序进入后台并被 *** 作系统杀死.似乎在恢复后我有2个IncidentScreenFragment来处理事件,一个有一个空的演示者(MVP)使我的应用程序崩溃.我的HomeActivity看起来像:overridefunonCreate(savedInstanceState:

我有一个使用VIEwPager显示片段的应用程序的问题.一切正常,直到应用程序进入后台并被 *** 作系统杀死.似乎在恢复后我有2个IncIDentScreenFragment来处理事件,一个有一个空的演示者(MVP)使我的应用程序崩溃.

我的HomeActivity看起来像:

    overrIDe fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentVIEw(R.layout.activity_main)        presenter.onVIEwCreated()        initVIEws(savedInstanceState)    }    private fun initVIEws(savedInstanceState: Bundle?){        mapVIEw.onCreate(savedInstanceState)        mapVIEw.getMapAsync(this)        initFragment()        initMenu()    }    private fun initFragment(){        homeFragment = HomeScreenFragment.newInstance()        incIDentFragment = IncIDentScreenFragment.newInstance()        chatFragment = ChatFragment.newInstance()        weatherFragment = WeatherFragment.newInstance()        vIEwPager.adapter = VIEwPagerAdapter(supportFragmentManager, this)        vIEwPager.offscreenPagelimit = 4        vIEwPager?.addOnPagechangelistener(object : VIEwPager.OnPagechangelistener {            overrIDe fun onPageScrollStateChanged(state: Int) {}            overrIDe fun onPageScrolled(position: Int, positionOffset: float, positionOffsetPixels: Int) {}            overrIDe fun onPageSelected(position: Int) {bottom_navigation.currentItem = position}        })    }    overrIDe fun getFragmentByPos(pos: Int): Fragment {        return when(pos){            0 -> homeFragment            1 -> incIDentFragment            2 -> chatFragment            3 -> weatherFragment            else -> {                homeFragment            }        }    }

我的适配器:

class VIEwPagerAdapter internal constructor(fm: FragmentManager, activity:infinite_software.intelligence_center.intelligencecenter.ui.home.FragmentManager) : FragmentPagerAdapter(fm) {    private val COUNT = 4    private val activity = activity    overrIDe fun getItem(position: Int): Fragment{        var fragment: Fragment? = null        when (position) {            0 -> fragment = activity.getFragmentByPos(0)            1 -> fragment = activity.getFragmentByPos(1)            2 -> fragment = activity.getFragmentByPos(2)            3 -> fragment = activity.getFragmentByPos(3)        }        return fragment!!    }    overrIDe fun destroyItem(container: VIEwGroup, position: Int, `object`: Any) {        super.destroyItem(container, position, `object`)    }    overrIDe fun getCount(): Int {        return COUNT    }    overrIDe fun getPageTitle(position: Int): CharSequence? {        return "Section " + (position + 1)    }}

每个Fragment都有一个返回new Fragment的静态方法:

    companion object {        fun newInstance(): HomeScreenFragment {            return HomeScreenFragment()        }    }

当应用程序在后台被杀死时,我发现有两个对象(Fragment)可以监听事件,一个用Presenter正确实例化,一个没有.

在我的抽象BaseFragment类下面:

abstract class BaseFragment<P : BasePresenter<BaseVIEw>> : BaseVIEw,Fragment() {    protected lateinit var presenter: P    overrIDe fun getContext(): Context {        return activity as Context    }    overrIDe fun onCreateVIEw(inflater: LayoutInflater, container: VIEwGroup?, savedInstanceState: Bundle?): VIEw? {        return super.onCreateVIEw(inflater, container, savedInstanceState)    }    overrIDe fun onVIEwCreated(vIEw: VIEw, savedInstanceState: Bundle?) {        super.onVIEwCreated(vIEw, savedInstanceState)        presenter = instantiatePresenter()    }    overrIDe fun showError(error: String) {        (activity as BaseActivity<BasePresenter<BaseVIEw>>).showError(error)    }    overrIDe fun showError(errorResID: Int) {        (activity as BaseActivity<BasePresenter<BaseVIEw>>).showError(errorResID)    }    abstract fun onBackpressed(): Boolean    /**     * Instantiates the presenter the Fragment is based on.     */    protected abstract fun instantiatePresenter(): P    abstract val TAG: String

事件片段代码:

class IncIDentScreenFragment: BaseFragment<IncIDentScreenPresenter>(), BaseVIEw, IncIDentVIEw, AlertFilterListener, AlertItemClickListener, IncIDentDetailListener {    var rvAdapter : IncIDentAdapter? = null    var state : Int = List_STATE    overrIDe fun instantiatePresenter(): IncIDentScreenPresenter {        return IncIDentScreenPresenter(this)    }    overrIDe val TAG: String        get() = "INCIDENT"    overrIDe fun getContext(): Context {        return activity as Context    }    overrIDe fun onCreateVIEw(inflater: LayoutInflater, container: VIEwGroup?, savedInstanceState: Bundle?): VIEw? {        super.onCreateVIEw(inflater, container, savedInstanceState)        return inflater.inflate(R.layout.fragment_incIDent, container, false)    }    overrIDe fun onVIEwCreated(vIEw: VIEw, savedInstanceState: Bundle?) {        super.onVIEwCreated(vIEw, savedInstanceState)        initVIEws()        presenter.onVIEwCreated()        initObserve()    }    private fun initVIEws(){        //Reclycler vIEw        alertRV.layoutManager = linearlayoutmanager(context)        rvAdapter = IncIDentAdapter(ArrayList(), context, this)        alertRV.adapter = rvAdapter        //Apply Listeners        headerBox.setFilterListener(this)        incIDentDetailVIEw.setListener(this)    }    overrIDe fun initObserve() {        //Init observe presenter model        val alertObserver = Observer<ArrayList<AlertModel>> { alerts ->            Timber.d("Data received from Presenter [$alerts]")            showAlertList(alerts)        }        presenter.filtereDalertList.observe(context as BaseActivity<BasePresenter<BaseVIEw>>,alertObserver)    }    overrIDe fun updateThisFilters(BoxState: Boolean, level: Int) {        presenter.updatefilterList(BoxState,level)    }    fun showOnlyThisLevel(level:Int){        presenter.showOnlyThisLevel(level)        headerBox.disableBoxExcept(level)    }    fun showAlertList(List: ArrayList<AlertModel>){        rvAdapter?.updateData(List)    }    overrIDe fun onItemClick(model: AlertModel) {        presenter.loaDalertDetail(model)    }    overrIDe fun showAlertDetail(model: AlertModel) {        incIDentDetailVIEw.setUpFromModel(model)        WhiteWizard.slIDeleftEffect(incIDentDetailVIEw,incIDentListRootElement)        state = DETAIL_STATE    }    overrIDe fun onbackFromDetailpressed() {        WhiteWizard.slIDeRightEffect(incIDentListRootElement,incIDentDetailVIEw)        state = List_STATE    }    overrIDe fun showLoader() {        loaderIncIDent.visibility = VIEw.VISIBLE    }    overrIDe fun hIDeLoader() {        loaderIncIDent.visibility = VIEw.INVISIBLE    }    overrIDe fun onBackpressed(): Boolean {        when(state){            List_STATE -> return false            DETAIL_STATE -> {                onbackFromDetailpressed()                return true            }            else -> return false        }    }    fun newInstance(): IncIDentScreenFragment {            return  IncIDentScreenFragment()    }}

当我点击homePage中的按钮显示我得到的片段内容:

 Process: XXXXXX, PID: 3192    kotlin.UninitializedPropertyAccessException: lateinit property presenter has not been initialized        at infinite_software.intelligence_center.intelligencecenter.base.BaseFragment.getPresenter(BaseFragment.kt:11)        at XXXXXX.ui.home.incIDentScreen.IncIDentScreenFragment.showOnlyThisLevel(IncIDentScreenFragment.kt:78)        at XXXXXX.ui.home.HomeActivity.filterDataWithSeverity(HomeActivity.kt:110)        at XXXXXX.ui.home.homeScreen.HomeScreenFragment.filterBy(HomeScreenFragment.kt:76)        at XXXXXX.ui.home.homeScreen.HomeScreenFragment$initVIEws.onClick(HomeScreenFragment.kt:56)

如果我尝试打印片段的ID,我从方法调用showOnlyThisLevel()和onBackpressed()获得2个不同的ID.我想念的是什么?

解决方法:

在仔细搜索证据之后,我必须得出结论,问题源于FragmentPagerAdapter代表AndroID支持库作者的方法的错误,没有明确指出抽象方法getItem(int position)应该返回一个新的实例片段而不仅仅是“获取一个实例”.

当然,我们可以做一些关于错误名称的事情,因为它已经在野外停留了7年,但至少我们可以修复你的代码中源于此问题的错误;)

不用多说,你的NPE的原因是onCreateVIEw(实例化你的Presenter)永远不会被调用.

发生这种情况是因为您在此处创建片段:

overrIDe fun onCreate(savedInstanceState: Bundle?) {    super.onCreate(savedInstanceState)    setContentVIEw(R.layout.activity_main)    ...    homeFragment = HomeScreenFragment.newInstance()    incIDentFragment = IncIDentScreenFragment.newInstance()}

您从FragmentPagerAdapter中的getItem(int position)内部返回此片段:

overrIDe fun getItem(position: Int): Fragment = when(position) {     ...     1 -> activity.incIDentFragment     ...}

所以我们对activity.incIDentFragment的了解是,在它中,永远不会调用onCreateVIEw().

这是因为它从未真正添加到FragmentManager并且从未在屏幕上显示.

这是因为Activity中的super.onCreate(savedInstanceState)使用他们的no-args构造函数通过反射重新创建所有片段,同时保留它们的标记(请参阅findFragmentByTag).

正如你在this answer中看到的那样,或者我可以在这里引用:

    // Do we already have this fragment?    String name = makeFragmentname(container.getID(), itemID);    Fragment fragment = mFragmentManager.findFragmentByTag(name);    if (fragment != null) {        if (DEBUG) Log.v(TAG, "Attaching item #" + itemID + ": f=" + fragment);        mCurTransaction.attach(fragment);    } else {        fragment = getItem(position);        if (DEBUG) Log.v(TAG, "Adding item #" + itemID + ": f=" + fragment);        mCurTransaction.add(container.getID(), fragment,                makeFragmentname(container.getID(), itemID));

仅当FragmentPagerAdapter为片段设置的片段标记找不到片段时才调用getItem(position)方法,在低内存条件杀死应用程序后自动重新创建片段.

因此,您的新片段(您在Activity中手动创建)永远不会被使用,因此它没有视图,从未初始化,从未添加到FragmentManager,它与VIEwPager中的实际内容不同,并且在崩溃时崩溃你叫它.繁荣!

解决方案是在FragmentPagerAdapter的getItem(position)方法中实例化Fragment.要获取片段的实例,请使用this answer.

总结

以上是内存溢出为你收集整理的android – 活动在后台被杀死后应用程序崩溃全部内容,希望文章能够帮你解决android – 活动在后台被杀死后应用程序崩溃所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1101706.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-28
下一篇2022-05-28

发表评论

登录后才能评论

评论列表(0条)

    保存