从导航菜单返回片段后,为什么我的 <EditText> 字段为空?

时间:2021-01-25 14:43:43

标签: android kotlin android-fragments

我的应用程序有问题,我有一个导航栏,我可以在片段之间切换,在第一个片段中,我可以查看我在第三个片段中添加的项目。我使用 MVVM 并且一切正常我在第三个片段中添加人员,它出现在第一个片段中,这里没问题,但是当我添加一些内容然后切换片段以查看更改然后切换到再次添加内容时,我的应用程序将 EditText 字符串视为空(即使它们不在应用程序的视图中)。

我在导航之间切换的代码:

fun openFragment(fragment: Fragment) {
        val transaction = supportFragmentManager.beginTransaction()
        transaction.replace(R.id.container, fragment)
        transaction.addToBackStack(fragment.tag)
        transaction.commit()
    }

    /**Navigation menu */
    val menuNavigationClickListener =
        BottomNavigationView.OnNavigationItemSelectedListener { item ->
            when (item.itemId) {
                R.id.navigation_products -> {
                    toolbar.title = "Products"
                    openFragment(productsFragment)
                    return@OnNavigationItemSelectedListener true
                }
                R.id.navigation_dishes -> {
                    toolbar.title = "Dishes"
                    openFragment(dishesFragment)
                    return@OnNavigationItemSelectedListener true
                }
                R.id.navigation_add -> {
                    toolbar.title = "Add"
                    openFragment(addFragment)
                    return@OnNavigationItemSelectedListener true
                }
            }
            false
        }

有什么建议吗?

编辑:发布第三个片段

class Add : Fragment(), AdapterView.OnItemSelectedListener {
val NEW_SPINNER_ID = 1
val ANOTHER_SPINNER_ID = 2
var productPosition: Int? = null
var dishPosition: Int? = null

fun showToast(context: FragmentActivity? = activity, message: String, duration: Int = Toast.LENGTH_LONG) {
    Toast.makeText(context, message, duration) .show()
}
/**Spinner implementation TODO */

override fun onNothingSelected(parent: AdapterView<*>?) {
    showToast(activity,"nothing selected ",3)
}

override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
    when (parent?.id) {
        1 -> {productPosition = position
            showToast(message ="product list")
        }
        else -> {dishPosition = position
            showToast(message = "dish list")
        }
    }
}


override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    val view: View = inflater.inflate(R.layout.fragment_add, container, false)




    /** initialize ui with viewmodel*/

    fun initializeUi() {

        // Get the AddViewModelFactory with all of it's dependencies constructed
        val factory = InjectorUtils.provideAddViewModelFactory()
        // Use ViewModelProviders class to create / get already created AddViewModel
        // for this view (activity)
        val viewModel = ViewModelProviders.of(requireActivity(), factory)
            .get(AddViewModel::class.java)

        /** BINDERS FOR BUTTONS AND FIELDS */
        val name     = view.findViewById<EditText>(R.id.product_name).text
        val price    = view.findViewById<EditText>(R.id.product_price).text
        val tax      = view.findViewById<EditText>(R.id.product_tax).text
        val waste    = view.findViewById<EditText>(R.id.product_waste).text
        val weightOfAddedProduct = view.findViewById<EditText>(R.id.product_weight)
        val addButton = view.findViewById<Button>(R.id.addProduct)
        val createDishButton = view.findViewById<Button>(R.id.new_dish_button)
        val addProductToDishBtn = view.findViewById<ImageButton>(R.id.add_product_to_dish)



        /** ADAPTERs FOR SPINNERs */
        var productAdapter = ArrayAdapter(requireActivity(),android.R.layout.simple_spinner_item,viewModel.getProducts().value!!.map { it.name })
        productAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
        val mySpinner = view.findViewById<Spinner>(R.id.mySpinner)
        with(mySpinner)
        {
            adapter = productAdapter
            setSelection(0, false)
            onItemSelectedListener = this@Add
            prompt = "Select product"
            gravity = Gravity.CENTER
        }
        mySpinner.id = NEW_SPINNER_ID


        var dishesAdapter = ArrayAdapter(requireActivity(),android.R.layout.simple_spinner_item,viewModel.getDishes().value!!.map{it.name})
        dishesAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
        val dishSpinner = view.findViewById<Spinner>(R.id.dishSpinner)
        with(dishSpinner){
            adapter = dishesAdapter
            setSelection(0,false)
            onItemSelectedListener = this@Add
            prompt = "Select dish"
            gravity = Gravity.CENTER
        }
        dishSpinner.id =  ANOTHER_SPINNER_ID


        /**OBSERVING LIVEDATA FROM ADDVIEWMODEL
         *  WHICH OBSERVES LIVEDATA IN REPOSITORY
         *  WHICH OBSERVES LIVEDATA FROM DAO */

        viewModel.getProducts().observe(this, Observer { products ->
            productAdapter.clear()
            products.forEach { product ->
                productAdapter.add(product.name)
            }
        })

        viewModel.getDishes().observe(this, Observer { dishes ->
            dishesAdapter.clear()
            dishes.forEach{dish ->
                dishesAdapter.add(dish.name)
            }

        })

        /** BUTTONS FUNCTIONALITY */

        createDishButton.setOnClickListener{
            CreateDish().show(childFragmentManager,CreateDish.TAG)
        }
        addButton.setOnClickListener{
            if(name.isNullOrEmpty()||
                price.isNullOrEmpty()||
                tax.isNullOrEmpty()||
                waste.isNullOrEmpty()){showToast(message = "Fill all data!")}
            else {
                val product = Product(
                    name.toString(),
                    price.toString().toDouble(),
                    tax.toString().toDouble(),
                    waste.toString().toDouble()
                )
                viewModel.addProducts(product)

                name.clear()
                price.clear()
                tax.clear()
                waste.clear()
            }
        }
        addProductToDishBtn.setOnClickListener{
            val pickedDish     = viewModel.getDishes().value!![this!!.dishPosition!!]
            val pickedProduct  = viewModel.getProducts().value!![this!!.productPosition!!]
            viewModel.addProductToDish(pickedDish,pickedProduct,weightOfAddedProduct.text.toString().toDouble())
        }

    }

    initializeUi()
    return view
}
companion object {
    fun newInstance():Add = Add()
    const val TAG = "Add"
}

1 个答案:

答案 0 :(得分:1)

我想我明白这个问题了。 因此,成功添加产品后,您将返回到片段编号 1(产品列表)。新产品在那里,太好了。 现在您将返回到第三个片段(添加产品),期望表单仍被填充(编辑文本字段等),但它们是空白的。

这样做的原因是第二次返回到第 3 个片段时,再次调用 onCreateView 并重新创建整个片段。在此 initializeUi 方法中,您没有填充文本字段(它不会记住您上次使用此片段时的值)。

您需要根据视图模型中的数据填充 EditText 方法中的 initializeUi 字段。

val name = view.findViewById<EditText>(R.id.product_name).text
name.text = viewModel.someLiveDataField.value

更新:

尝试从这些行的末尾删除 .text(并重命名它们):

val nameEditText     = view.findViewById<EditText>(R.id.product_name)
val priceEditText    = view.findViewById<EditText>(R.id.product_price)
val taxEditText      = view.findViewById<EditText>(R.id.product_tax)
val wasteEditText    = view.findViewById<EditText>(R.id.product_waste)

现在,在您的 OnClickListener 中,将其更改为:

val product = Product(
                    nameEditText.text,
                    priceEditText.text.toDouble(),
                    taxEditText.text.toDouble(),
                    wasteEditText.text.toDouble()
                )

(如果语法稍有错误,请见谅)。