从 Activity 的 Fragment 中保存数据

Posted

技术标签:

【中文标题】从 Activity 的 Fragment 中保存数据【英文标题】:Save Data from Fragment in Activity 【发布时间】:2019-10-16 19:59:27 【问题描述】:

将 Fragment 中的数据保存在 Activity 中不起作用

设置:我有 2 个 Activity 和 2 个动态创建的片段

在横向模式下,Activity Main 包含两个 Fragment, 否则只有 Fragment Main 并通过 ActivityForResult 启动 Activity 编辑

活动编辑包含片段编辑

Activity Main 有一个数据库

Fragment Main 从 Activity 中获取一个 List

片段编辑修改列表

我的方法是在包含列表的 Fragment Main 被销毁时将列表保存在 Activity 中。

当前状态 调用 ActivityForResult 时数据未写入数据库 在横向模式下也不行。

让我感到困惑的是,数据是在打开显示时写入的,但我不会在任何时候更新 MainActivity 中的列表

 MainActivity 
================
override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        getTable() // gets Data from DataBase

        if (savedInstanceState == null) 
            supportFragmentManager.beginTransaction()
                .add(R.id.frame_main, MainFragment.newInstance(dbList, true), "mainFragment")
                .commit()

         else 
            // Destroys the Fragment because I want to load it with different config
            var  mainFragment = supportFragmentManager.findFragmentByTag("mainFragment") as MainFragment
            mainFragment.onDestroyView()
            // Checks if it is Landscape
            if (TabletHelper.isLandscape(this)) 
                supportFragmentManager.beginTransaction().replace(
                    R.id.frame_main,
                    MainFragment.newInstance(dbList, false),
                    "mainFragment"
                ).commit()
                supportFragmentManager.beginTransaction().replace(
                    R.id.frame_edit,
                    EditFragment.newInstance(null, null, true, null),
                    "editFragment"
                ).commit()
             else 
                supportFragmentManager.beginTransaction().replace(
                    R.id.frame_main,
                    MainFragment.newInstance(dbList, true),
                    "mainFragment"
                ).commit()
            
        

    

// interface implementation from the MainFragment
    override fun passList(list: ArrayList<Product>) 
        dbList.clear()
        dbList.addAll(list)
    
// Write the list to the DataBase
    override fun onDestroy() 
        super.onDestroy()
        productsDBHelper.writeAllProducts(dbList, TABLE_NAME_MAIN)
    




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

        if(savedInstanceState != null && savedState == null) 
            savedState = savedInstanceState.getBundle(BUNDLE)
        
        if(savedState != null) 
            productList.addAll(savedState!!.getParcelableArrayList<Product>(PRODUCT_LIST_KEY)!!)
        
        savedState = null

 //doing something with Layout...

        
    
// save bundel when onDestroyView is called 
   override fun onDestroyView() 
        super.onDestroyView()
        savedState = saveState()

    
// Interface to pass the data to the Activity
    interface  OnFragmentMainClicked 
        fun passList(list: ArrayList<Product>)
    //..

    


//creating Bundle for instance
    private fun saveState():Bundle
        var state = Bundle()
        state.putParcelableArrayList(PRODUCT_LIST_KEY,productList)
        return state
    
// Save Instance
    override fun onSaveInstanceState(outState: Bundle) 
        super.onSaveInstanceState(outState)
        if (savedState != null )
            outState.putBundle(BUNDLE,savedState)
        else
            outState.putBundle(BUNDLE,saveState())
        
    









//My Thought was to save the Data always when when onDestroyView in the Fragment is called
     override fun onDestroyView() 
        super.onDestroyView()
        savedState = saveState()
        onFragmentMainClicked.passList(productList)
    
//But it is not working. Result is that it clears whole list

【问题讨论】:

使用interface作为Activity和Fragment之间的通信器。这种做法非常适合开发。 我更新了代码。我正在使用一个界面,但是何时使用它以及为什么当我转动显示器时列表会更新。顺便说一句谢谢你的回应 【参考方案1】:

我不知道您为什么首先将列表设置为onDestroyView()。如果您想要此列表,则在活动生效之前进行通信的步骤。因此,要实现这一点,请创建另一种方法来在您的界面中获取您的列表getList(),这将返回您的列表。因为你必须同时实现passList(list: List&lt;Type&gt;)getList(): List&lt;Type&gt;。现在,在您的活动中全局获取一个列表对象,填充到您的 passList(list) 方法中并返回全局列表对象(已填充)。 然后只需使用接口对象调用getList()。我希望你能通过界面得到你的清单。 希望能帮助到你。告诉我。

【讨论】:

嘿,我解决了这个问题,但我不明白为什么它会这样。我作为 ParcelableArrayList 传递给 Fragment 的 Activity 列表总是在我对 Fragment 进行一些修改时更新。现在在 Activity 中,我总是将 onPause 列表写入我的数据库,这样 Activity 列表中的任何更改都不会丢失。因此,在我的情况下不需要该界面,但非常感谢您的想法。也许你可以解释一下为什么我通过参数传递给片段的列表也会覆盖活动中的列表。

以上是关于从 Activity 的 Fragment 中保存数据的主要内容,如果未能解决你的问题,请参考以下文章

Fragment 回退栈 传递参数,点击切换图片使用Fragment ListView

fragment--总结

Activity数据恢复时移除Fragment数据

如何从一个activity中跳转到一个fragment

Activity与Fragment易混点归纳

Intent 不会从 Fragment 启动 Activity