英文:
Passing data between two fragments through async task
问题
以下是您提供的内容的翻译:
我刚刚开始使用Java开发(Android应用程序),但我遇到了一个我不知道如何解决的问题。
所以我有两个片段:
1)具有条形码扫描器的片段
2)只有一个简单文本视图的片段
该应用程序应能够扫描条形码,根据扫描结果获取API响应,将其反序列化为Java对象,然后显示第二个片段中文本视图中的一个变量的值。
我已经实现了条形码扫描器和从API获取数据并将其转换为Java对象的类。问题是我找不到一种将条码结果发送到处理API数据检索的类的方法,以及如何将对象发送到第二个片段。
有人能否请指导我如何正确实现它?
1)条形码片段
public class BarcodeFragment extends Fragment {
private CodeScanner mCodeScanner;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
final Activity activity = getActivity();
View root = inflater.inflate(R.layout.barcode_fragment, container, false);
CodeScannerView scannerView = root.findViewById(R.id.scanner_view);
mCodeScanner = new CodeScanner(activity, scannerView);
mCodeScanner.setDecodeCallback(new DecodeCallback() {
@Override
public void onDecoded(@NonNull final Result result) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(activity.getApplicationContext(), result.getText(), Toast.LENGTH_SHORT).show();
}
});
}
});
scannerView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mCodeScanner.startPreview();
}
});
return root;
}
@Override
public void onResume() {
super.onResume();
mCodeScanner.startPreview();
}
@Override
public void onPause() {
mCodeScanner.releaseResources();
super.onPause();
}
}
2)从API获取数据并将其转换为Java对象的类
public class RetrieveFeedTask extends AsyncTask<Void, Void, String> {
Product productFromDatabase;
String resultString;
public RetrieveFeedTask(String barcodeResult){
resultString = barcodeResult;
}
protected void onPreExecute() {
}
protected String doInBackground(Void... urls) {
try {
URL url = new URL("https://api.appery.io/rest/1/apiexpress/api/example/Products?apiKey=12345678&Barcode=" + resultString);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
bufferedReader.close();
return stringBuilder.toString();
}
finally{
urlConnection.disconnect();
}
}
catch(Exception e) {
Log.e("ERROR", e.getMessage(), e);
return null;
}
}
protected void onPostExecute(String response) {
if(response == null) {
response = "THERE WAS AN ERROR";
}
Log.i("INFO", response);
deSerializeProduct(response);
}
public void deSerializeProduct(String response){
response = response.substring(1,response.length() - 3);
StringBuilder stringBuilder = new StringBuilder(response);
stringBuilder.append(",\"productId\":\"23323123sdasd\"}"); // for testing
String responseToDeSerialize = stringBuilder.toString();
ObjectMapper mapper = new ObjectMapper();
try {
productFromDatabase = mapper.readValue(responseToDeSerialize, Product.class);
} catch (IOException e) {
e.printStackTrace();
}
}
}
3)购物车片段类,其中对象的名称应显示在文本视图中
public class CartFragment extends Fragment {
static TextView showReceivedData;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.cart_fragment, parent, false);
showReceivedData = (TextView) view.findViewById(R.id.resultCode);
return view;
}
}
请注意,这些代码片段是按照您提供的原始内容翻译的。如果需要进一步的帮助或解释,请随时提问。
英文:
I have just started out with Java development(android app) and I stumbled upon a problem I don't know how to solve.
So I have two fragments:
- Fragment with barcode scanner
- Fragment with just a simple textview
The app should be able to scan barcode, get API response based on the scan result, deserialize it into a Java object and then show value of one variable in the textview located in the second fragment.
I have already implemented the barcode scanner and class to get data from API and turn it into a Java object. The problem is that I can't find a way to send the barcode result to the class that handles the API data retrieval and also how to send the object to the second fragment.
Can someone please direct me in the right way on how to implement it correctly?
1)Barcode fragment
public class BarcodeFragment extends Fragment {
private CodeScanner mCodeScanner;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
final Activity activity = getActivity();
View root = inflater.inflate(R.layout.barcode_fragment, container, false);
CodeScannerView scannerView = root.findViewById(R.id.scanner_view);
mCodeScanner = new CodeScanner(activity, scannerView);
mCodeScanner.setDecodeCallback(new DecodeCallback() {
@Override
public void onDecoded(@NonNull final Result result) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(activity.getApplicationContext(), result.getText(), Toast.LENGTH_SHORT).show();
}
});
}
});
scannerView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mCodeScanner.startPreview();
}
});
return root;
}
@Override
public void onResume() {
super.onResume();
mCodeScanner.startPreview();
}
@Override
public void onPause() {
mCodeScanner.releaseResources();
super.onPause();
}
}
-
Class to get data from API and turn it into JAVA object
public class RetrieveFeedTask extends AsyncTask<Void, Void, String> {
Product productFromDatabase;
String resultString;public RetrieveFeedTask(String barcodeResult){
resultString = barcodeResult;
}protected void onPreExecute() {
}
protected String doInBackground(Void... urls) {
try { URL url = new URL("https://api.appery.io/rest/1/apiexpress/api/example/Products?apiKey=12345678&Barcode=" + resultString); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); try { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); StringBuilder stringBuilder = new StringBuilder(); String line; while ((line = bufferedReader.readLine()) != null) { stringBuilder.append(line).append("\n"); } bufferedReader.close(); return stringBuilder.toString(); } finally{ urlConnection.disconnect(); } } catch(Exception e) { Log.e("ERROR", e.getMessage(), e); return null; }
}
protected void onPostExecute(String response) {
if(response == null) { response = "THERE WAS AN ERROR"; } Log.i("INFO", response); deSerializeProduct(response);
}
public void deSerializeProduct(String response){
response = response.substring(1,response.length() - 3);StringBuilder stringBuilder = new StringBuilder(response); stringBuilder.append(",\"productId\":\"23323123sdasd\"}"); // for testing String responseToDeSerialize = stringBuilder.toString(); ObjectMapper mapper = new ObjectMapper(); try { productFromDatabase = mapper.readValue(responseToDeSerialize, Product.class); } catch (IOException e) { e.printStackTrace(); }
}
} -
Cart fragment class where to name of the object should appear in the textview
public class CartFragment extends Fragment {
static TextView showReceivedData;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
// Defines the xml file for the fragment
View view = inflater.inflate(R.layout.cart_fragment, parent, false);
showReceivedData = (TextView) view.findViewById(R.id.resultCode);
return view;}
}
答案1
得分: 0
asynctask不应该超出启动它的活动或片段的生命周期。我假设您可能会在网络请求进行时显示某种加载状态。以下是一些选项:
-
如果这两个片段在同一个活动中,您可以将扫描的结果传递给活动,启动网络请求,切换片段,并将请求结果发送到第二个片段。
-
扫描器片段可以获取条形码数据,启动请求,显示加载状态,并在结果返回时将其打包在捆绑包中,供第二个片段阅读。
-
如果适用于您的应用程序,可以颠倒前面的模型,只发送条形码结果到捆绑包中,并在显示加载状态的同时,由第二个片段启动请求。
确切的选择将取决于您的应用程序的流程和结构。此外,您可能希望考虑使用另一种多线程选项,而不是asynctask,因为它已被弃用,Google正在努力引导开发人员摆脱使用它。一些替代方案包括Java并发库、RxJava,或者如果您愿意在项目中使用Kotlin,则可以使用Kotlin协程。
英文:
The asynctask shouldn't outlive the lifecycle of the activity or fragment that starts it. I'm assuming you probably will display some sort of loading status while the network request happens. Here are some options:
-
If the two fragments are in the same activity, you could pass the result of the scan to the activity, kick off the network request, swap fragments, and send the request result to the second fragment.
-
The scanner fragment can get the barcode data, kick off the request, show the loading state, and when the result returns, package in the bundle, which the second fragment can read.
-
Invert the previous model, if it fits your app better, and send just the barcode result in the bundle, and have the second fragment kick off the request while displaying the loading status.
The exact choice will depend on the flow and structure of your app. Additionally, you may want to look into using another multithreading option instead of asynctask, as it has been deprecated and Google is trying to move developers away from it. Some alternatives are the Java concurrency library, RxJava, or if you are willing to use Kotlin in your project, Kotlin coroutines.
答案2
得分: 0
使用 Bundle 在 Activity 和片段之间传递数据
尝试使用以下代码在两个片段之间传递数据
Bundle bundle = new Bundle();
bundle.putString("scanner_data", "myData");
Fragment fragment = new HomeFragment();
fragment.setArguments(bundle);
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.add(R.id.framContainer, fragment, "Tag");
ft.commit();
如何获取数据
Bundle bundle = getArguments();
英文:
Use Bundle to add pass data between Activity and fragments
try This code to Pass data between two fragments
Bundle bundle=new Bundle();
bundle.putString("scanner_data","myData");
Fragment fragment=new HomeFragment();
fragment.setArguments(bundle);
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.add(R.id.framContainer, fragment, "TAg");
ft.commit();
How to get data
Bundle bundle=getArguments();
专注分享java语言的经验与见解,让所有开发者获益!
评论