有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java For循环在解析期间访问JSON数据中的键时未完成

我正在尝试为youtube频道创建一个应用程序,为此我使用youtube数据API v3。接收到的数据是JSON格式的,需要解析才能在recyclerview中显示

在解析JSON时,我遇到了一个非常不寻常的问题,我的for循环没有完成对JSON数组的迭代。但这并不是每次都会发生。只有当我尝试访问一个名为videoId的密钥时才会发生这种情况。尽管当我尝试访问与videoId相同嵌套级别(如“publishedAt”)的其他键时,代码运行良好

在过去的两天里,我一直试图解决这个问题,但都没有成功。请帮忙

以下是我的MainActivity、VideoAdapter、Video(模型数据类)代码:

主要活动。爪哇:

public class MainActivity extends AppCompatActivity {

    URL url = null;
    String resultString = null;
    RecyclerView rv;
    VideoAdapter adapter;
    ArrayList<Video> titles;

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

        rv = (RecyclerView) findViewById(R.id.rv_display);
        url = NetworkUtils.buildUrlFromUsername(Config.FOR_USERNAME);
        Log.i("ayusch", "url = " + url);
        new YoutubeQueryTask().execute(url);
        Log.i("ayusch", "After task");

    }

    public void formatJSON(String resultString) {
        new JSONParseTask().execute(resultString);
    }

    public class YoutubeQueryTask extends AsyncTask<URL, Void, String> {


        @Override
        protected String doInBackground(URL... params) {
            URL builtUrl = params[0];
            resultString = "no result";
            try {
                resultString = NetworkUtils.getResponseFromUrl(builtUrl);
            } catch (IOException e) {
                e.printStackTrace();
            }

            return resultString;
        }

        @Override
        protected void onPostExecute(String s) {

            formatJSON(s);

            RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
            rv.setLayoutManager(layoutManager);
            rv.setHasFixedSize(true);
            adapter = new VideoAdapter(titles);
            rv.setAdapter(adapter);
            Log.i("ayusch", "" + adapter.getItemCount());
        }
    }


    public class JSONParseTask extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... params) {
            JSONObject itemsObj, thumbnailsObject, defaultObject, obj, snippetObj;
            ArrayList<Video> videoTitles = new ArrayList<>();
            String title, thumbnailUrl, description, videoId,date;
            try {
                itemsObj = new JSONObject(resultString);
                JSONArray itemsArray = itemsObj.getJSONArray("items");

                for (int i = 0; i < itemsArray.length(); i++) {

                    obj = itemsArray.getJSONObject(i);
                    snippetObj = obj.getJSONObject("snippet");

                    title = snippetObj.getString("title");
                    thumbnailsObject = snippetObj.getJSONObject("thumbnails");
                    defaultObject = thumbnailsObject.getJSONObject("default");
                    thumbnailUrl = defaultObject.getString("url");
                    description = snippetObj.getString("description");

                    videoId = (obj.getJSONObject("id")).getString("videoId");
                    //date = snippetObj.getString("publishedAt");
                    videoTitles.add(new Video(title, thumbnailUrl, description, videoId));

                    Log.i("ayusch", "length of array = " + i);
                }


            } catch (Exception e) {
                e.printStackTrace();
            }

            titles = videoTitles;
            return null;
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            adapter.notifyDataSetChanged();
        }
    }

}

视频适配器。爪哇:

public class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.CustomHolder> {

    private int maxNumItems = 25;
    ArrayList<Video> titles;

    public VideoAdapter(ArrayList<Video> titles) {
        this.titles = titles;
    }

    @Override
    public CustomHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View root = LayoutInflater.from(parent.getContext()).inflate(R.layout.row, parent, false);
        CustomHolder holder = new CustomHolder(root, parent.getContext());
        return holder;
    }

    @Override
    public void onBindViewHolder(CustomHolder holder, int position) {

        holder.tv_title.setText((titles.get(position).title));
        String url = titles.get(position).thumbnailUrl;
        Picasso.with(holder.tv_title.getContext()).load(url).into(holder.iv_thumbnail);
        holder.tv_description.setText((titles.get(position)).description);
    }


    @Override
    public int getItemCount() {
        return titles.size();
    }

    public class CustomHolder extends RecyclerView.ViewHolder {
        TextView tv_title,tv_description;
        ImageView iv_thumbnail;
        Context c;

        public CustomHolder(View itemView, Context context) {
            super(itemView);

            tv_title = (TextView) itemView.findViewById(R.id.tv_video_title);
            iv_thumbnail = (ImageView) itemView.findViewById(R.id.iv_video_thumbnail);
            tv_description = (TextView) itemView.findViewById(R.id.tv_video_description);
            c = context;
        }


    }
}

录像带。爪哇:

public class Video {
    String title;
    String thumbnailUrl;
    String description;
    String videoId;

    Video(String vidTitle, String url, String desc ,String vidId) {
        title = vidTitle;
        thumbnailUrl = url;
        description = desc;
        videoId = vidId;

    }
}

以下是一些json(未经验证,仅为整个数据的一部分):

{
 "kind": "youtube#searchListResponse",
 "etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/x-MGNU9lsGdyhXyip2D886I5NP8\"",
 "nextPageToken": "CBkQAA",
 "regionCode": "IN",
 "pageInfo": {
  "totalResults": 28,
  "resultsPerPage": 25
 },
 "items": [
  {
   "kind": "youtube#searchResult",
   "etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/uYSFXJP9T4MDWQg_zw335jVDIZw\"",
   "id": {
    "kind": "youtube#video",
    "videoId": "SckdKFwLA_8"
   },
   "snippet": {
    "publishedAt": "2017-04-30T09:45:26.000Z",
    "channelId": "UCYBeH5TdGbIQSKWoWFYUAYw",
    "title": "B.o.B - Airplanes ft. Hayley Williams [HINDI COVER] | Papa Pandey",
    "description": "This is a cover song made by me @Papa Pandey lyrics - @Papa Pandey like if u love this song original video link ...",
    "thumbnails": {
     "default": {
      "url": "https://i.ytimg.com/vi/SckdKFwLA_8/default.jpg",
      "width": 120,
      "height": 90
     },
     "medium": {
      "url": "https://i.ytimg.com/vi/SckdKFwLA_8/mqdefault.jpg",
      "width": 320,
      "height": 180
     },
     "high": {
      "url": "https://i.ytimg.com/vi/SckdKFwLA_8/hqdefault.jpg",
      "width": 480,
      "height": 360
     }
    },
    "channelTitle": "Papa Pandey",
    "liveBroadcastContent": "none"
   }
  },
  {
   "kind": "youtube#searchResult",
   "etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/uK0xksJsOifxE8jj28n8xRIM5h8\"",
   "id": {
    "kind": "youtube#video",
    "videoId": "T3bGsPaaj8M"
   },
   "snippet": {
    "publishedAt": "2017-04-25T16:41:28.000Z",
    "channelId": "UCYBeH5TdGbIQSKWoWFYUAYw",
    "title": "Tharki Roomie",
    "description": "",
    "thumbnails": {
     "default": {
      "url": "https://i.ytimg.com/vi/T3bGsPaaj8M/default.jpg",
      "width": 120,
      "height": 90
     },
     "medium": {
      "url": "https://i.ytimg.com/vi/T3bGsPaaj8M/mqdefault.jpg",
      "width": 320,
      "height": 180
     },
     "high": {
      "url": "https://i.ytimg.com/vi/T3bGsPaaj8M/hqdefault.jpg",
      "width": 480,
      "height": 360
     }
    },
    "channelTitle": "Papa Pandey",
    "liveBroadcastContent": "none"
   }
  }
}

欢迎提出任何性能改进建议!!:)


共 (3) 个答案

  1. # 1 楼答案

    而不是直接访问

    videoId = (obj.getJSONObject("id")).getString("videoId");
    

    你应该先检查一下

    (obj.getJSONObject("id"))
    

    里面有一个videoId对象。我相信你可以通过以下方式做到这一点:

    JSONObject idObj = obj.getJSONObject("id");
    if (idObj != null && idObj.hasElement("videoId)) {
        videoId = idObj.getString("videoId");
    }
    
  2. # 2 楼答案

    尝试使用GSON进行json解析

    Gson is a Java library that can be used to convert Java Objects into their JSON representation. It can also be used to convert a JSON string to an equivalent Java object.

    粘贴JSON here并生成POJO类,然后调用new Gson.fromJson(json,Pojoclass.class)并完成它

  3. # 3 楼答案

    “for loop is not completing”不应该发生,除非您退出它们或获得异常

    在您的代码中,我怀疑您在这一行中遇到了异常:

    videoId = (obj.getJSONObject("id")).getString("videoId");
    

    我建议你调试代码,看看到底发生了什么(可能你得到的一些Json对象没有"id"标记)

    要解决此问题,您可以尝试以下方法:

    JSONObject idJSONObject = obj.getJSONObject("id");
    if (idJSONObject != null) {
        if (idJSONObject.hasElement("videoId)) {
            videoId = idJSONObject.getString("videoId");
        }
    }