J'essaye de créer une application pour une chaîne youtube et pour cela j'utilise Youtube Data API v3. Les données reçues sont au format JSON et doivent être analysées pour être affichées dans recyclerview.

Lors de l'analyse de JSON, je me suis retrouvé coincé dans un problème très inhabituel où ma boucle for ne termine pas son itération sur le tableau JSON. Mais cela n'arrive pas à chaque fois. Cela ne se produit que lorsque j'essaye d'accéder à une clé appelée videoId. Bien que lorsque j'essaie d'accéder à d'autres clés au même niveau imbriqué (comme "publishedAt") que le videoId, le code fonctionne bien.

J'essaye de contourner ce problème depuis 2 jours mais en vain. Veuillez aider !!

Voici mon code pour MainActivity, VideoAdapter, Video (classe de données de modèle):

MainActivity.java:

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();
        }
    }

}

VideoAdapter.java:

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;
        }


    }
}

Video.java:

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;

    }
}

Voici quelques-uns des json (non validés, seulement une partie de l'ensemble des données):

{
 "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"
   }
  }
}

Toutes les suggestions d'amélioration des performances sont également les bienvenues !! :)

0
Ayusch 1 mai 2017 à 17:34

3 réponses

Meilleure réponse

"for loop is not complete" ne devrait pas se produire à moins que vous ne les quittiez ou que vous n'obteniez une exception.

Dans votre code, je soupçonne que vous obtenez une exception dans cette ligne:

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

Je vous suggère de déboguer le code et de voir exactement ce qui se passe (peut-être que certains des objets Json que vous obtenez n'ont pas de balise "id".

Pour résoudre, vous pouvez essayer ceci:

JSONObject idJSONObject = obj.getJSONObject("id");
if (idJSONObject != null) {
    if (idJSONObject.hasElement("videoId)) {
        videoId = idJSONObject.getString("videoId");
    }
}
2
Doron Yakovlev-Golani 1 mai 2017 à 14:48

Essayez d'utiliser GSON pour l'analyse Json.

Gson est une bibliothèque Java qui peut être utilisée pour convertir des objets Java en leur représentation JSON. Il peut également être utilisé pour convertir une chaîne JSON en un objet Java équivalent.

Collez votre ici JSON et faites générer votre classe POJO, puis appelez new Gson.fromJson(json,Pojoclass.class) et c'est fait.

1
Jozef Dochan 1 mai 2017 à 14:47

Au lieu d'accéder directement

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

Vous devez d'abord vérifier si

(obj.getJSONObject("id"))

Contient un objet videoId. Je pense que vous pouvez le faire en:

JSONObject idObj = obj.getJSONObject("id");
if (idObj != null && idObj.hasElement("videoId)) {
    videoId = idObj.getString("videoId");
}
2
The Hungry Androider 1 mai 2017 à 14:55