Kotlin 片段可以触发 activity 的 onNewIntent

Kotlin can a fragment trigger an activity's onNewIntent

我目前正在开发一款使用 Zebra SDK 的扫描仪应用程序。
在我找到的示例和文档中,onTouchListener 创建了一个新的 Intent(扫描)并广播它。在重写的 onNewIntent 方法中,意图被解码并返回扫描值。

只要我使用 1 activity 并且没有片段,这一切都很好,但是对于我正在创建的应用程序,我希望有 1 activity 和多个片段。 目前一切都发生在 1 activity(和一个视图)中,但这有点混乱并且不是做事的理想方式,所以我最终会拆分 activity。

我尝试创建片段并使用 safeargs 在它们之间传递数据。但我无法弄清楚如何启动意图并从片段中捕获结果。我尝试在我的片段中添加一个 onTouchListener,

下面是 activity 中的当前代码。我没有任何碎片,因为到目前为止我所有的尝试都失败了。

 override fun onTouch(view: View?, motionEvent: MotionEvent?): Boolean {
        if (view?.getId() == R.id.btnScanner) {
            if (motionEvent?.getAction() == MotionEvent.ACTION_DOWN) {
                //  Button pressed, start scan
                val dwIntent = Intent()
                dwIntent.action = "com.symbol.datawedge.api.ACTION"
                dwIntent.putExtra("com.symbol.datawedge.api.SOFT_SCAN_TRIGGER", "START_SCANNING")
                dwIntent.putExtra("Type", "START")
                sendBroadcast(dwIntent)
            } else if (motionEvent?.getAction() == MotionEvent.ACTION_UP) {
                //  Button released, end scan
                val dwIntent = Intent()
                dwIntent.action = "com.symbol.datawedge.api.ACTION"
                dwIntent.putExtra("com.symbol.datawedge.api.SOFT_SCAN_TRIGGER", "STOP_SCANNING")
                dwIntent.putExtra("Type", "END")
                sendBroadcast(dwIntent)
            }
        }
        return true
    }

 override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        if (intent.getStringExtra("Type") != "START") {
           //This would be for the first fragment
            if (personId.text.toString().isEmpty()) {
                val id = decodeScan((intent))
                personId.text = id
                lockId()
            } else {
              //This would be in the second fragment, after the user signed in by scanning his personal barcode
                if (productId.hasFocus() || productId.text.isEmpty()) {
                    val res = decodeScan(intent)
                    productId.text = res
                } else if (locationId.hasFocus() || (locationId.text.isEmpty() && productId.text.isNotEmpty())) {
                    val res = decodeScan(intent)
                    val location = (locations.filter { x -> x.contains(res) }).first()
                    locationId.setText(location)
                }
            }
        }
    }

onNewIntent 方法属于 Activity,因此您不能在片段中使用它。您可以做的是,在提供的 onNewIntent 调用时将数据传递给您的片段,您可以引用该片段。

var fragment; //assign default value to fragment

override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
// you can add fragment based checks in this method                                       
   to work as you want
 if (fragment is YourFragment) {

    if (intent.getStringExtra("Type") != "START") {
       //This would be for the first fragment
        if (personId.text.toString().isEmpty()) {
            val id = decodeScan((intent))
            personId.text = id
            lockId()
        }
     }
    }else if (fragment is YourSecondFragment) {{
            if (productId.hasFocus() || productId.text.isEmpty()) {
                val res = decodeScan(intent)
                productId.text = res
            } else if (locationId.hasFocus() || (locationId.text.isEmpty() && 
               productId.text.isNotEmpty())) {
                val res = decodeScan(intent)
                val location = (locations.filter { x -> x.contains(res) }).first()
                locationId.setText(location)
            }
        }
    }
}

onNewIntent 仅在 Activity 中可用,因此您需要使意图对片段可用。

为此,您可以使用 MutableLiveData 和 ViewModel。

class MyViewModel: ViewModel() {
    val intent = MutableLiveData<Intent?>() 
}

然后

class MyActivity: AppCompatActivity() {
    private val  myViewModel by viewModels<MyViewModel>() 
    
    override fun onCreate( savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.my_activity)
        val myViewModel = myViewModel
        myViewModel.intent = intent
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        myViewModel.intent = intent
    } 
}

class MyFragment: Fragment() {
    private val MyViewModel by activityViewModels<MyViewModel>() 

    ... 
}

并且您可以使用生命周期所有者 this 在 onCreate 中观察当前意图。