从 AsyncTask 携带和重用信息(json 字符串)?

Posted

技术标签:

【中文标题】从 AsyncTask 携带和重用信息(json 字符串)?【英文标题】:Carrying and reusing information (json string) from an AsyncTask? 【发布时间】:2019-04-07 00:51:22 【问题描述】:

我创建了一个带有 3 个 TextViews 的简单 android 应用,然后通过不同的类运行 AsyncTask 任务,下一步是传递信息并使任务可重用

任务将使用一个字符串 (URL) 和 MainActivity 的上下文

任务将发出一个简单的 REST 请求 (GET)检索一个 json 字符串。

然后我创建了另一个类,它获取 json 响应并创建一个 .json 文件将其保存到

..../0/Notes/launch.json

“Notes”文件夹是我自己通过file.mkdirs()创建的。

在 MainActivity 中,我创建了一个 InputStream 来读取 AsyncTask 保存的 .json 文件,但是一旦我尝试打开它,它就会给我一个 FileNotFoundException

这是我的 MainActivity.class 的代码

package com.example.root.example;

import android.Manifest;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.TextView;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

public class MainActivity extends AppCompatActivity 

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ActivityCompat.requestPermissions(this,new String[]Manifest.permission.WRITE_EXTERNAL_STORAGE, 200);
    String url = "https://api.spacexdata.com/v3/launches/upcoming"; //Copy the url and open it in your browser to see the json.

    AsyncCall asyncCall = new AsyncCall(getApplicationContext());
    asyncCall.myAsyncTask(url);

   try 
        InputStream inputStream = this.getAssets().open("launch.json");
        int size = inputStream.available();
        byte[] buffer = new byte[size];
        inputStream.read(buffer);
        inputStream.close();
        String jsonStringFromFile= new String(buffer,"UTF-8");
        JSONObject launchObject = new JSONObject(jsonStringFromFile);
        System.out.println(launchObject.get("flight_number"));
     catch (IOException e) 
        e.printStackTrace();
     catch (JSONException e) 
        e.printStackTrace();
    
  

这是 AsyncCall.class(制作和检索 json 等)

package com.example.root.example;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Environment;

import java.io.IOException;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class AsyncCall 

FileCreator fileCreator = new FileCreator();
private final Context myContext;

public AsyncCall(final Context context) 
    myContext = context;


public void myAsyncTask(final String url) 

    AsyncTask asyncTask = new AsyncTask() 
        @Override
        protected Object doInBackground(Object[] objects) 
            OkHttpClient okHttpClient = new OkHttpClient();
            Request request = new Request.Builder()
                    .url(url)
                    .build();
            Response response = null;
            try 
                response = okHttpClient.newCall(request).execute();
                fileCreator.generateFile(myContext, myContext.getString(R.string.fileName), response.body().string());

             catch (IOException ioe) 
                ioe.getMessage();
            
            return null;
        
    .execute();
  

我要归档什么?我正在尝试保存信息(此处为 json)并使其像 Falcon 9 一样可重复使用。

问题在于将信息传递给不同的类。 如果有替代解决方案(除了保存 .json 文件)来解决此问题,请不要犹豫发布它。

这只是我的第一个问题,第二个问题会在您打开 api link 并看到不止一个 JSON 字符串后出现(0,1,2,3,4...即将到来的任务) .

我完全不知道如何解决第一个问题,更不用说第二个问题了,我已经重新开始了几次,前段时间多次。

【问题讨论】:

如果你使用的是okhttp,你不需要asynctask 我正在使用 okhttp。如果没有 asnytask 它将如何工作,因为理论上它会给我一个 networkonmainThread 异常 【参考方案1】:

在您的活动中,您可以像这样获取 JSON

OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
okHttpClient.newCall(request).enqueue(new Callback() 
    @Override
    public void onResponse(Call call, final Response response) throws IOException   
        try 
            final String responseData = response.body().string();
            JSONObject json = new JSONObject(responseData);

            String flightNumber = json.getString("flight_number");
            // TODO: Load number into a TextView
         catch (JSONException e) 
            e.printStackTrace();
        
    
);

不过,查看您的 API 响应,您实际上需要 new JSONArray(responseData),并且您必须遍历它才能获取每个单独对象的航班号

【讨论】:

这就是问题所在。我需要让它可重复使用。这样我就可以应用下一个任务的航班号的值(如果您访问 api 页面,您会看到有不止 1 个任务即将到来。所以我需要能够获取那些即将到来的任务的 json 字符串也是。但我会定义。试试你的解决方案(没有 asynctask)。 如果你想折射这个,那么new Callback() 可以在任何地方定义。一个单独的类、一个字段、一个局部变量等。这里的重点是.enqueue() 执行后台网络调用而不是加载AsyncTask。关于值,您需要使用JSONArray,此处给出的答案实际上将无法解析响应 这解决了我的问题。如评论部分所述,您必须将 jsonobject 替换为 jsonarray。您将不得不使用 jsonarray.getJSONObject.... 来访问这些值。

以上是关于从 AsyncTask 携带和重用信息(json 字符串)?的主要内容,如果未能解决你的问题,请参考以下文章

使用 AsyncTask 从 JSON 中获取数据

Android AsyncTask 无法从 php-mysql 检索 JSON 字符串

如何从 Android AsyncTask 更改活动 UI?

来自使用 AsyncTask 解析的 JSON 对象的 setText [重复]

AsyncTask下载JSON

如何在android的Asynctask中显示json响应[重复]