片段必须在创建之前调用寄存器 registerForActivityResult()

Posted

技术标签:

【中文标题】片段必须在创建之前调用寄存器 registerForActivityResult()【英文标题】:Fragments must call register registerForActivityResult() before they are created 【发布时间】:2021-09-30 01:47:53 【问题描述】:

我正在开发购物应用程序,我创建了一个用于将产品添加到产品列表的片段。我需要获得将照片添加到产品的读取外部存储权限,因此我尝试在我的片段中使用 registerForActivityResult() 并且我收到此错误。我是 android 编程的新手,所以我不知道我是否以正确的方式使用它。

我尝试了其他问题的所有答案,但它们也没有奏效。对不起,我的英语不好。感谢您的帮助。

java.lang.IllegalStateException: Fragment AddActivity after being created. Fragments must call rHgS5orgPvsuzJ7shn8vw28y1XaePY4uDP() before they are created (i.e. initialization, onAttach(), or onCreate()).
        at androidx.fragment.app.Fragment.prepareCallInternal(Fragment.java:3482)
        at androidx.fragment.app.Fragment.rHgS5orgPvsuzJ7shn8vw28y1XaePY4uDP(Fragment.java:3449)
        at com.example.TheDentalSupplies.AddActivity.showImageChooser(AddActivity.kt:120)
        at com.example.TheDentalSupplies.AddActivity.requestPermission(AddActivity.kt:96)
        at com.example.TheDentalSupplies.AddActivity.onViewCreated$lambda-1(AddActivity.kt:66)
        at com.example.TheDentalSupplies.AddActivity.lambda$gx8TAUa5Jk3WDkvGOWG0oB39kiM(Unknown Source:0)
        at com.example.TheDentalSupplies.-$$Lambda$AddActivity$gx8TAUa5Jk3WDkvGOWG0oB39kiM.onClick(Unknown Source:4)
        at android.view.View.performClick(View.java:7125)
        at android.view.View.performClickInternal(View.java:7102)
       

AddActivity.kt:

class AddActivity : Fragment() 
private lateinit var img:ImageView
private lateinit var requestLauncher: ActivityResultLauncher<String>

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? 

        requestLauncher = registerForActivityResult(
            ActivityResultContracts.RequestPermission()
        ) 
            if(it)
                    showImageChooser(img)
                else
                    Toast.makeText(requireContext(), "PERM", Toast.LENGTH_SHORT).show()
                
        
        return inflater.inflate(R.layout.addpost, container, false)
    

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) 
        super.onViewCreated(view, savedInstanceState)
        val image1 = view.findViewById<ImageView>(R.id.addImage1)
        val image2 = view.findViewById<ImageView>(R.id.addImage2)
        val image3 = view.findViewById<ImageView>(R.id.addImage3)
        val image4 = view.findViewById<ImageView>(R.id.addImage4)
        val image5 = view.findViewById<ImageView>(R.id.addImage5)

        image1.setOnClickListener 
            requestPermission(image1)
            
        image2.setOnClickListener 
            requestPermission(image2)
        
        image3.setOnClickListener 
            requestPermission(image3)
        
        image4.setOnClickListener 
            requestPermission(image4)
        
        image5.setOnClickListener 
            requestPermission(image5)
        
        val publishBtn = view.findViewById<Button>(R.id.addPublishBtn)

        publishBtn.setOnClickListener  addItem(view) 

    


    private fun requestPermission(imageView: ImageView) 
            img = imageView

            if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) 

                showImageChooser(imageView)
            
            else

                ActivityCompat.requestPermissions(requireActivity(), arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), Constants.READ_STORAGE_PERMISSION_CODE)
                requestLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)


            


    


    fun showImageChooser(imageView: ImageView) 
        val galleryIntent = Intent(
            Intent.ACTION_PICK,
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI
        )

        val launchSomeActivity = registerForActivityResult(ActivityResultContracts.StartActivityForResult())  result ->
            if (result.resultCode == Activity.RESULT_OK) 
                val data: Intent? = result.data
                if (data != null)
                    try 
                        val mSelectedImageFileUri = data.data!!

                        //setUserPic.setImageURI(Uri.parse(selectedImageFileUri.toString()))
                        GlideLoader(requireContext()).loadUserPicture(mSelectedImageFileUri,imageView)

                        //FireStoreClass().uploadImgCloud(requireActivity(), mSelectedImageFileUri)


                    catch (e: IOException)
                        e.printStackTrace()
                        Toast.makeText(
                            requireContext(),
                            "Image selection failed",
                            Toast.LENGTH_SHORT
                        ).show()
                    
                
            
        

        launchSomeActivity.launch(galleryIntent)
    

    private fun addItem(view: View) 
        //val image1 = view.findViewById<ImageView>(R.id.addImage1)
        val addProductName = view.findViewById<TextInputEditText>(R.id.addTitleEditText).text.toString()
        val addProductDesc = view.findViewById<TextInputEditText>(R.id.addDescEditText).text.toString()
        val addProductPrice = view.findViewById<TextInputEditText>(R.id.addPrice).text.toString()
        val addProductCat = view.findViewById<TextInputEditText>(R.id.selectCategoryEt).text.toString()

        when
            TextUtils.isEmpty(addProductName.trim  it <= ' ' ) -> Toast.makeText(activity,
                "Please Enter Product Name.",
                Toast.LENGTH_SHORT).show()

            TextUtils.isEmpty(addProductDesc.trim  it <= ' ' ) -> Toast.makeText(activity,
                "Please Enter Product Description.",
                Toast.LENGTH_SHORT).show()

            TextUtils.isEmpty(addProductCat.trim  it <= ' ' ) -> Toast.makeText(activity,
                "Please Select Product Category.",
                Toast.LENGTH_SHORT).show()

            TextUtils.isEmpty(addProductPrice.trim  it <= ' ' ) -> Toast.makeText(activity,
                "Please Enter Product Price.",
                Toast.LENGTH_SHORT).show()

            else -> 
                //val index = 0
                val firebaseUser: String = Firebase.auth.currentUser!!.uid
                val product = ProductItem(R.drawable.add_box,
                    addProductName,
                    0.0,
                    "Serhat Yilmaz",
                    addProductPrice.toInt(),
                    addProductDesc,
                    addProductCat.toInt(),
                    firebaseUser)

                //Datasource.productList.add(index,product)
                FireStoreClass().addProduct(requireActivity(), product)
                //Toast.makeText(activity, "Product Published!", Toast.LENGTH_SHORT).show()
                val action = AddActivityDirections.actionAddPostNavActivityToProductFragment()
                view.findNavController().navigate(action)
            
        
    



【问题讨论】:

这能回答你的问题吗? Update to androidx.fragment:fragment:1.3.0-alpha08: registerForActivityResult not allowed after onCreate anymore. How to use after onCreate? 你读过Activity Result documentation吗?它准确地解释了如何使用 API。 感谢您的回答。我设法通过将launchSomeActivity剪切并粘贴到onViewCreated函数的底部来修复它 【参考方案1】:

我设法通过将 launchSomeActivity 剪切并粘贴到 onViewCreated 函数的底部来修复它。

【讨论】:

嗨,我有一个非常相似的情况,如果你将launchSomeActivity移动到onviewCreated(),你是如何将ImageUri设置为imageview的。谢谢

以上是关于片段必须在创建之前调用寄存器 registerForActivityResult()的主要内容,如果未能解决你的问题,请参考以下文章

片段 null 必须是公共静态类才能从实例状态正确重新创建

如何缓存片段视图

在片段中实现对话框时,必须在添加内容之前请求窗口功能

在函数调用之前保存 XMM 寄存器

R0~R16寄存器作用(转)

在过程调用和操作 ecx 寄存器之前保存 ECX 寄存器