onDetach()不要求从一个片段移动到另一个片段

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了onDetach()不要求从一个片段移动到另一个片段相关的知识,希望对你有一定的参考价值。

[当我从FragB(从活动工具栏启动的bottomsheetfragment)返回值到FragA(从活动的viewpager返回值,并通过接口调用FragA的方法以使用新数据再次访问API时,它会给我以下内容例外:

java.lang.IllegalStateException:无法为分离的片段创建ViewModelProvider

在将数据从FragB转到活动后,我正在使用以下方法从活动中调用FragA的方法:

val getFragment = pagerAdapter.getItem(viewPager.currentItem)

        if(getFragment is GrowthStoryFragment)
            getFragment.myfilterOptions(countryId, dateRange, specs)

因此从this SO线程读取后,它说去进行空检查或在onAttach中重新初始化viewModel,但是这里的奇怪行为是,当我从以下位置启动bottomsheetfragment(FragB)时,没有调用FragA的生命周期方法活动的工具栏,当我在按钮上单击dismiss()FragB时,则仅调用FragB的生命周期方法,再次没有Viewpager片段FragA的生命周期方法被调用,因此,当片段被分离时,现在应该从哪里重新调用-初始化viewModel和其他实例?

[请帮助我了解这种情况。

更新:这是活动代码:

class ViewDetailsActivity : BaseActivity(), FilterOptionsDialogFragment.onApplyEventListener, BusinessUnitDialogFragment.afterDoneClick 


    private lateinit var pagerAdapter: ViewDetailsFragmentAdapter
    private var myFragmentFlag = 0

    private var TAG = "ViewDetailsActivity"

    override fun getContentView(): Int = R.layout.activity_view_details

    override fun onViewReady(savedInstanceState: Bundle?, intent: Intent?) 


        tabLayout!!.addTab(tabLayout!!.newTab().setText("Growth Story"))
        tabLayout!!.addTab(tabLayout!!.newTab().setText("Share Story"))
        tabLayout!!.addTab(tabLayout!!.newTab().setText("Purchase Dynamics"))
        tabLayout!!.addTab(tabLayout!!.newTab().setText("Brand Health Track"))
        tabLayout.tabMode = TabLayout.MODE_SCROLLABLE
        tabLayout.tabGravity = Gravity.CENTER
        tabLayout.setTabTextColors(Color.parseColor("#a1a1a1"), Color.parseColor("#ff8a00"))

        pagerAdapter = ViewDetailsFragmentAdapter(supportFragmentManager, tabLayout!!.tabCount)
        viewPager.adapter = pagerAdapter
        viewPager.isFocusableInTouchMode = true

        scrollListener()

        viewPager!!.addOnPageChangeListener(TabLayout.TabLayoutOnPageChangeListener(tabLayout))

        tabLayout!!.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener 
            override fun onTabSelected(tab: TabLayout.Tab) 
                viewPager!!.currentItem = tab.position
                when (tab.position) 
                    0 -> 
                        myFragmentFlag = 0
                        left_scroll.visibility = View.GONE
                        right_scroll.visibility = View.VISIBLE
                    
                    1 -> 
                        myFragmentFlag = 1
                        right_scroll.visibility = View.VISIBLE
                    
                    2 -> 
                        myFragmentFlag = 2
                        left_scroll.visibility = View.VISIBLE
                        right_scroll.visibility = View.VISIBLE
                    
                    3 -> 
                        myFragmentFlag = 3
                        left_scroll.visibility = View.VISIBLE
                        right_scroll.visibility = View.GONE
                    
                
            

            override fun onTabUnselected(tab: TabLayout.Tab) 

            

            override fun onTabReselected(tab: TabLayout.Tab) 

            
        )

        tvTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen._16ssp))
        tvTitle.setText("Category Deep Dive")
        ivBack.setOnClickListener(View.OnClickListener 
            finish()
        )
        ivLogo.setOnClickListener(View.OnClickListener 
            val addFrag = FilterOptionsDialogFragment.newInstance()
            addFrag.show(supportFragmentManager, "add")
        )

        vd_edit_icon.setOnClickListener(
            val buFrag = BusinessUnitDialogFragment.newInstance()
            buFrag.show(supportFragmentManager, "add")
        )

        vd_edit_icon.visibility = View.VISIBLE
    

    fun scrollListener() 
        left_scroll.setOnClickListener(View.OnClickListener 
            val itemnum = viewPager.currentItem
            viewPager.currentItem = itemnum - 1
        )

        right_scroll.setOnClickListener(View.OnClickListener 
            val itemnum = viewPager.currentItem
            viewPager.currentItem = itemnum + 1
        )
    

    override fun someEvent(countryId: String?, dateRange: String?, specs: String?) 
        val getFragment = pagerAdapter.getItem(viewPager.currentItem)

        if(getFragment is GrowthStoryFragment)
            getFragment.myfilterOptions(countryId, dateRange, specs)
        else if(getFragment is ShareStoryFragment)
            getFragment.myfilterOptions(countryId, dateRange, specs)
        else if(getFragment is PurchaseDynamicsFragment)
            getFragment.myfilterOptions(countryId, dateRange, specs)
        else if(getFragment is BrandHealthFragment)
            getFragment.myfilterOptions(countryId, dateRange, specs)
        
    

    override fun onDoneClicked(item: String) 

        val getFragment = pagerAdapter.getItem(viewPager.currentItem)

        if(getFragment is GrowthStoryFragment)
            getFragment.getBuName(item)
        else if(getFragment is ShareStoryFragment)
            getFragment.getBuName(item)
        else if(getFragment is PurchaseDynamicsFragment)
            getFragment.getBuName(item)
        else if(getFragment is BrandHealthFragment)
            getFragment.getBuName(item)
        

    


片段适配器:

import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentStatePagerAdapter

class ViewDetailsFragmentAdapter(supportFragmentManager: FragmentManager,internal var totalTabs: Int): FragmentStatePagerAdapter(supportFragmentManager) 
    override fun getItem(position: Int): Fragment? 
        when (position) 
            0 ->  return GrowthStoryFragment()
            1 -> return ShareStoryFragment()
            2 -> return PurchaseDynamicsFragment()
            3 -> return BrandHealthFragment()
            else -> return null
        
    

    // this counts total number of tabs
    override fun getCount(): Int 
        return totalTabs
    


片段A:

class GrowthStoryFragment : Fragment() 

    private val TAG = "GrowthStoryFragment"
    private  lateinit var disposable : Disposable
    private lateinit var responseSpinner : List<RespCat>
    private lateinit var responseFirstBarChart : List<RespBrand>
    private lateinit var RespDon : List<RespDon>
    private lateinit var responseSecondBarChart : List<RespDist>

    companion object

        private lateinit var myApplicationContext : Context
        private var countryID = "1"
        private var date = "MAT TY"
        private var spec  = "val"

        private var businessUnitID = "2"
        private var category = "Fresh Milk"
        private var firstReportTypeId = "1"       //fixed for growth story and share story
        private var isGroup = "false"             //fixed to false
    

    private lateinit var userModel : UserViewModel

    private val backendApi = WinRetrofitHelper.winApiInstance()

    override fun onAttach(context: Context?) 
        super.onAttach(context)
        Log.e(TAG, "OnAttach")
        userModel = ViewModelProviders.of(this)[UserViewModel::class.java]

    

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? 
        Log.e(TAG, "OnCreateView")
        return inflater.inflate(R.layout.fragment_growth_story, container, false)
    

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) 
        super.onViewCreated(view, savedInstanceState)
        Log.e(TAG, "OnViewCreated")
        myApplicationContext = context!!.applicationContext
        getSpinnerResponse(businessUnitID, isGroup,firstReportTypeId)
//        getSuperRegionName(countryID, date,spec," ",businessUnitID, category, firstReportTypeId, isGroup)

        growth_spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener
            override fun onNothingSelected(parent: AdapterView<*>?) 

            

            override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) 
                val item  = parent?.getItemAtPosition(position) as RespCat
                category = item.nameValue
                Log.e(TAG,"Category name is: " + category)
                getSuperRegionName(countryID, date,spec," ",businessUnitID, category, firstReportTypeId, isGroup)
            
        

    

    private fun getSpinnerResponse(businessUnitID: String, isGroup: String, firstReportTypeId: String)

        userModel.getResponseGrowthSpinner(businessUnitID, isGroup, firstReportTypeId)
        userModel.responseGrowthSpinner.observe(this,
                Observer 
                    Utils.debugger("FRAG ", "$it")
                    growth_spinner.adapter = GrowthSpinnerAdapter(it)
                )
    

    private fun getSuperRegionName(countryID: String, date: String, spec: String, superMarket: String,businessUnitID: String, category: String, firstReportTypeId: String, isGroup: String) 

        userModel.getResponseSuperRegion(countryID)
        userModel.responseSuperRegion.observe(this,
                Observer 
                    Utils.debugger("FRAG ", "$it")
                    getDataFromApi(countryID, date, spec, it!!.get(0).nameValue, businessUnitID, category, firstReportTypeId, isGroup)
                )
    

    private fun getColorID(position: Int): Int 
        try 
            val rnd = Random
            when (position) 
                0 -> return R.color.brand_almarai
                1 -> return R.color.brand_alsafi
                2 -> return R.color.brand_nadec
                3 -> return R.color.brand_sadafco
                4 -> return R.color.brand_nestle
                5 -> return R.color.brand_amul
                6 -> return R.color.brand_nada
            
            return Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256))
        catch (e :Exception)
            e.printStackTrace()
        
        return 1
    

     fun myfilterOptions(countryId: String?, dateRange: String?, specs: String?)
         userModel = ViewModelProviders.of(this)[UserViewModel::class.java]
         getSuperRegionName(countryId!!,dateRange!!,specs!!.toLowerCase()," ",businessUnitID, category, firstReportTypeId, isGroup)
        Log.e(TAG, "Growth Story Fragment:" +countryId!!+" "+dateRange!!+" "+specs!!.toLowerCase()+ " "+businessUnitID+ " "+category+ " "+firstReportTypeId+ " "+isGroup)
    

    override fun onDestroy() 
        super.onDestroy()
        Log.e(TAG, "Ondestroy")
        disposable.dispose()
    

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        Log.e(TAG, "OnCreate")
    

    override fun onActivityCreated(savedInstanceState: Bundle?) 
        super.onActivityCreated(savedInstanceState)
        Log.e(TAG, "OnActivitycreated")
    

    override fun onPause() 
        super.onPause()
        Log.e(TAG, "OnPause")
    

    override fun onStart() 
        super.onStart()
        Log.e(TAG, "OnStart")
    

    override fun onResume() 
        super.onResume()
        Log.e(TAG, "OnResume")
    

    override fun onStop() 
        super.onStop()
        Log.e(TAG, "OnStop")
    

    override fun onDestroyView() 
        super.onDestroyView()
        Log.e(TAG, "Ondestroyview")
    

    override fun onDetach() 
        super.onDetach()
        Log.e(TAG, "OnDetach")
    


FragB代码:

class FilterOptionsDialogFragment : BottomSheetDialogFragment(), View.OnClickListener 

    private var myResp: List<RespBu>? = null
    private lateinit var myView: View
    private lateinit var customList: ArrayList<RespBu>
    private var dateRange: String = ""
    private var specrange: String = ""
    private lateinit var onmyApplyEventListener: onApplyEventListener
    private var TAG = "FilterOptionsDialogFragment"

    val pref: AppPreference by lazy 
        AppPreference.getInstance(context!!)
    

    companion object 
        fun newInstance(): FilterOptionsDialogFragment 
            return FilterOptionsDialogFragment()
        
    

    override fun onCreateView(inflater: LayoutInflater,
                              @Nullable container: ViewGroup?,
                              @Nullable savedInstanceState: Bundle?): View? 
        myView = inflater.inflate(R.layout.filter_options_layout, container, false)
        Log.e(TAG, "OnCreateView")
        // get the views and attach the listener

        val backendApi = WinRetrofitHelper.winApiInstance()
        val request = backendApi.getBUCountry()

        request.enqueue(object : Callback<List<RespBu>> 
            override fun onFailure(call: Call<List<RespBu>>?, t: Throwable?) 

            

            override fun onResponse(call: Call<List<RespBu>>?, response: Response<List<RespBu>>?) 
                val spinner = myView.findViewById<Spinner>(R.id.filter_options_spinner)

                spinner.adapter = Spinner_filter_options(getNewList(response?.body()))
                if(pref.getString("BuID") != null && !pref.getString("BuID").equals(""))

                    if(pref.getBoolean(Site.BUSINESS_UNIT_FRONT)!=null && pref.getBoolean(Site.BUSINESS_UNIT_FRONT))
                        filter_options_spinner.setSelection(pref.getString("BuID").toInt()-1)
                    else
                        filter_options_spinner.setSelection(pref.getString("BuID").toInt()-1)
                
            
        )

        return myView
    

    override fun onStart() 
        super.onStart()
        Log.e(TAG, "OnStart")
    

    private fun getNewList(mylist: List<RespBu>?): List<RespBu> 
        if(pref.getBoolean(Site.BUSINESS_UNIT_FRONT)!=null && pref.getBoolean(Site.BUSINESS_UNIT_FRONT))
            return mylist!!
        else
            customList = ArrayList()
            customList.add(RespBu("0", 0, "Global", 0))
            for (item in mylist.orEmpty()) 
                customList.add(item)
            
            return customList
        

    

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) 
        super.onViewCreated(view, savedInstanceState)
        try 

            if (pref.getString("dateName") != null && !pref.getString("dateName").equals("")) 
                if (pref.getString("dateName").equals("YTD"))
                    date_ytd.isChecked = true
                else
                    date_mat.isChecked = true
            

            if (pref.getString("specName") != null && !pref.getString("specName").equals("")) 
                if (pref.getString("specName").equals("VAL"))
                    spec_val.isChecked = true
                else
                    spec_vol.isChecked = true
            

            val dateradiogroup = view.findViewById<RadioGroup>(R.id.date_radio_group)
            val specradiogroup = view.findViewById<RadioGroup>(R.id.spec_radio_group)

            view.findViewById<ImageView>(R.id.view_close).setOnClickListener(View.OnClickListener 
                dismiss()
            )

            view.findViewById<Button>(R.id.apply).setOnClickListener(View.OnClickListener 
                val dateRadioBtn = view.findViewById<RadioButton>(dateradiogroup.checkedRadioButtonId)
                val specRadioBtn = view.findViewById<RadioButton>(specradiogroup.checkedRadioButtonId)
                val respBu = view.findViewById<Spinner>(R.id.filter_options_spinner).selectedItem as RespBu

                val buName = respBu.keyValue.toString()
                val dateName = dateRadioBtn.text.toString()
                val specName = specRadioBtn.text.toString()

                pref.saveString("BuID", filter_options_spinner.selectedItemId.toString())
                pref.saveString("dateName", dateName)
                pref.saveString("specName", specName)
                pref.saveString("BuName", respBu.keyValue.toString())

                onmyApplyEventListener.someEvent(buName, dateName + " TY", specName)
                Log.e("Filter item", respBu.nameValue + " " + dateRadioBtn.text)
                dismiss()
            )


            view.findViewById<Spinner>(R.id.filter_options_spinner).onItemSelectedListener = object : OnItemSelectedListener 
                override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) 

                

                override fun onNothingSelected(parent: AdapterView<*>?) 

                
            
        catch (e: Exception)
            e.printStackTrace()
        
    

    override fun onClick(p0: View?) 

    

    interface onApplyEventListener 
        fun someEvent(countryId: String?, dateRange: String?, specs: String?)
    

    override fun onAttach(activity: Activity?) 
        super.onAttach(activity)
        Log.e(TAG, "OnAttach")
        onmyApplyEventListener = activity as onApplyEventListener
    



    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        Log.e(TAG, "onCreate")
    

    override fun onActivityCreated(savedInstanceState: Bundle?) 
        super.onActivityCreated(savedInstanceState)
        Log.e(TAG, "OnActivitycreated")
    

//    override fun onAttach(context: Context?) 
//        super.onAttach(context)
//        onmyApplyEventListener = context as onApplyEventListener
//        Log.e(TAG, "OnAttach")
//    

    override fun onPause() 
        super.onPause()
        Log.e(TAG, "OnPause")
    

    override fun onResume() 
        super.onResume()
        Log.e(TAG, "OnResume")
    

    override fun onStop() 
        super.onStop()
        Log.e(TAG, "OnStop")
    

    override fun onDestroyView() 
        super.onDestroyView()
        Log.e(TAG, "Ondestroyview")
    

    override fun onDestroy() 
        super.onDestroy()
        Log.e(TAG, "Ondestroy")
    

    override fun onDetach() 
        super.onDetach()
        Log.e(TAG, "OnDetach")
    


答案

ViewModels应该针对应用程序上下文启动。像这样:someViewModel = activity.let ViewModelProvider(requireActivity())。get(SomeViewModel :: class.java)

尽管您没有粘贴适当的代码部分-我怀疑您将ViewModel生命周期与片段相关联-您可以通过片段内的requireContext()获得它。

尝试使用requireActivity()

由于提供了代码,因此进行了更新:userModel = ViewModelProviders.of(this)[UserViewModel :: class.java]

this-是对Fragment的引用。我盲目的猜测写的是正确的。使用requireActivity()

另一答案

下一个有趣的事物:onAttachContext isn't supported on all platforms

以上是关于onDetach()不要求从一个片段移动到另一个片段的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android 中单击 ImageView 时从一个片段移动到另一个片段?

从一个片段移动到另一个片段时如何自动选择底部导航?

OnDetach/onAttach 片段重新创建片段活动

如何在单击 RecyclerView 项目时从一个片段移动到另一个片段

设置onclick侦听器在android中无法从一个片段移动到另一个活动[重复]

想要使用片段从导航抽屉活动移动到另一个屏幕,以在所有屏幕上显示抽屉