问题描述
我目前正在开发一个使用 Zebra SDK 的扫描仪应用。
在我找到的示例和文档中,onTouchListener 创建一个新的 Intent(扫描)并广播它。在重写的 onNewIntent 方法中,意图被解码并返回扫描值。
只要我使用 1 个活动且没有片段,这一切都很好,但是对于我正在创建的应用程序,我希望有 1 个活动和多个片段。 目前一切都发生在 1 个活动(和一个视图)中,但这有点混乱,而且不是理想的做事方式,所以我最终会拆分活动。
我尝试创建片段并使用安全参数在它们之间传递数据。但我不知道如何开始意图并从片段中捕获结果。我尝试在我的片段中添加一个 onTouchListener,其中
以下是活动中的当前代码。我没有任何碎片,因为到目前为止我所有的尝试都失败了。
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 中可用,因此您需要使 Intent 可用于片段。
为此,您可以使用 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 中的当前意图。
方法 onNewIntent 属于 Activity,因此您不能在片段中使用它。您可以做的是,在提供的 onNewIntent 调用时将数据传递给您的片段,您可以引用该片段。
import React,{useCallback,useEffect,useState} from 'react';
import {ActivityIndicator,Dimensions,Text,View} from 'react-native';
import firestore from '@react-native-firebase/firestore';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import FolloweringScreens from './FolloweringScreens';
import {TouchableOpacity} from 'react-native-gesture-handler';
const {width,height} = Dimensions.get('screen');
function Following({urlname,navigation}) {
const [followingData,setfollowingData] = useState();
const [loading,setLoading] = useState(true);
// Following counts,displayname,image
const fetchData = useCallback(() => {
const dataRef = firestore().collection('usernames');
dataRef
.doc(urlname)
.collection('Following')
.limit(25)
.onSnapshot((snapshot) => {
let promises = [];
snapshot.forEach((doc) => {
const promise = dataRef
.doc(doc.id.toLowerCase())
.get()
.then((followerDoc) => {
const data = followerDoc.data();
return {
profileName: doc.id,displayName: data.displayName
? data.displayName
: data.userName,followerCount:
data.followers !== undefined ? data.followers : 0,followingCount:
data.following !== undefined ? data.following : 0,image: data.imageUrl ? data.imageUrl : null,};
});
promises.push(promise);
});
Promise.all(promises)
.then((res) => setfollowingData(res))
.then(setLoading(false));
});
},[]);
useEffect(() => {
const dataRef = firestore().collection('usernames');
const cleanup = dataRef
.doc(urlname)
.collection('Following')
.limit(25)
.onSnapshot(fetchData);
return cleanup;
// fetchData();
},[urlname,fetchData]);
return (
<>
<View
style={styles}>
<TouchableOpacity onPress={() => navigation.openDrawer()}>
<Icon name="menu" color="#222" size={30} />
</TouchableOpacity>
<Text style={{left: width * 0.05}}>Following</Text>
</View>
{loading ? (
<ActivityIndicator size="large" color="black" />
) : (
<>
<FolloweringScreens data={followingData} />
</>
)}
</>
);
}
export default Following;