尝试使用 Volley 和 GSON 从空数组中读取

Attempt to read from a null array using Volley and GSON

我正在尝试制作的音乐播放器中使用 Volley。

以下是我在音乐播放器中定义歌曲的方式。我有这个 "song object" 和一些属性

SongObject {

    public String albumArtURI;

    // Some other attributes 
}

为了得到albumArtURI,我对其进行了查询。如果 URI 不存在,我尝试从互联网上下载图像 URL,但出现此错误:

Attempt to read from a null array

下面是从互联网获取图像 url 并将其分配给歌曲对象的代码

 if(songObject.albumArtURI != null){

                    // The URI exists, so we leave as is

                } else {

                    // The album art URI does not exist,
                    // so we try to pull an album art .jpg URL down from iTunes
                    ServiceHandler serviceHandler = new ServiceHandler(MainActivity.this);
                    serviceHandler.getJSON_URL();               

                    songObject.albumArtURI = serviceHandler.JSONObjectsList[0].artworkUrl30; 
                    // Throws error "Attempt to read from a null array"
                }

所以从上面的代码可以看出,这一行抛出了错误

songObject.albumArtURI = serviceHandler.JSONObjectsList[0].artworkUrl30; 
// Gives error "Attempt to read from a null array"

但是,serviceHandler.JSONObjectsList[0].artworkUrl30 不应为空数组。

并且从后面class中的行可以看出,通过打印语句,上述变量不为空

Log.v("TAG",String.valueOf(JSONObjectsList[0].artworkUrl30)); 
// Prints http://is4.mzstatic.com/image/thumb/Music6/v4/68/b5/27/68b5273f-7044-8dbb-4ad1-82473837a136/source/30x30bb.jpg    

这里是 class 本身:

public class ServiceHandler {

    Context ctx;
    SongInfo[] JSONObjectsList;
    String albumArtURI;
    String url = "https://itunes.apple.com/search?term=michael+jackson";

    public ServiceHandler(Context ctx){

        this.ctx = ctx;
    }

    public void getJSON_URL(){

        RequestQueue requestQueue = Volley.newRequestQueue(ctx);

        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(url, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {

                // If there is a response, do this
                if (response != null) {

                    // Get the number of JSON objects on the web-page
                    int resultCount = response.optInt("resultCount");

                    // If there is a JSON object on the web-page, do this
                    if (resultCount > 0) {

                        // Get a gson object
                        Gson gson = new Gson();

                        // Get a JSONArray from the results
                        JSONArray jsonArray = response.optJSONArray("results");

                        // If the array exists, do this
                        if (jsonArray != null) {

                            // Convert the JSONArray into a Java object array 
                            JSONObjectsList = gson.fromJson(jsonArray.toString(), SongInfo[].class);

                            // Prints http://is4.mzstatic.com/image/thumb/Music6/v4/68/b5/27/68b5273f-7044-8dbb-4ad1-82473837a136/source/30x30bb.jpg
                            Log.v("TAG",String.valueOf(JSONObjectsList[0].artworkUrl30));                                                          
                        }
                    }
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e("LOG", error.toString());
            }
        });

        requestQueue.add(jsonObjectRequest);
    }

    public class SongInfo {

        // Some attributes

        public String artworkUrl30;

        // Some more attributes
    }
}

所以我认为问题与 Volley 的异步性质有关?

我正在尝试读取数组 "populated" 之前吗?

当 Volley 完成它的工作时,数组最终会被填充吗?

你的假设是正确的,这是因为异步。当 Volley 完成它的任务(即调用和执行 onResponse 方法)时,它们的数组将有数据。您可以使用接口从中获取数据。

定义接口

public interface MyInterface {
    public void myTask (SongInfo[] songInfo)
}

然后在您的 getJSON_URL 方法中使用接口作为参数

getJSON_URL (MyInterface myInterface) {
...
@Override
public void onResponse(JSONObject response) {
.....
myInterface.myTask(JSONObjectsList);
}

然后在你的主要 class

...
serviceHandler.getJSON_URL(new MyInterface);
@Override 
public void myTask (SongInfo[] songInfo) {
...
songObject.albumArtURI = serviceHandler.JSONObjectsList[0].artworkUrl30;
...
}
...