由于在android中解析JSON字符串响应而导致错误

时间:2017-04-30 19:11:54

标签: java android json video youtube

我正在尝试为youtube频道创建应用,并希望在recyclerview中显示视频列表。我正在使用YoutubeData API v3。我得到一个JSON字符串响应作为我的查询的回报,我手动解析它。

我创建了一个名为Video的类,用于存储有关对象中视频的信息,然后将其添加到ArrayList以传递给recyclerview适配器。最初它工作正常,但随着我想传递给Video对象的细节数量增加,recyclerview停止工作。它只显示最新的两个视频,其余视频不显示。

只要我将videoId传递给适配器,回收站视图就会停止工作。我尝试使用AsyncTask在单独的线程上解析json,但它不起作用。我长期陷入这个错误,无法找出原因。请帮忙!!

这是我的代码:

MainActivity.java:

import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;


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


    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;
            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");
                    videoTitles.add(new Video(title, thumbnailUrl, description,videoId));
                    Log.i("ayusch", "length of array = " + i);
                }


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

           titles=videoTitles;
            return null;
        }
    }

}

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

Error ( just two videos displayed )

Without videoId being passed. It should look like this.

另外,请随意为性能建议任何代码改进。我仍处于学习阶段,想要编写出色的性能代码,这个应用程序需要一段时间才能在recyclerview中加载json响应。

2 个答案:

答案 0 :(得分:0)

1。执行titles ArrayList initialization并从adapter方法设置RecyclerView onCreate()

对于每次数据提取操作,

2。titles清除JSONParseTask列表。

3。Video个对象添加到列表titles而不是videoTitles

4。在将每个项目添加到adapter.notifyDataSetChanged()列表后,请致电RecyclerView更新titles

更新MainActivity,如下所示:

import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;


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

        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
        rv.setLayoutManager(layoutManager);
        rv.setHasFixedSize(true);

        titles = new ArrayList<Video>();
        adapter = new VideoAdapter(titles);
        rv.setAdapter(adapter);

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

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

        @Override
        protected String doInBackground(String... params) {
            JSONObject itemsObj, thumbnailsObject, defaultObject, obj, snippetObj;

            String title, thumbnailUrl, description, videoId;
            try {
                itemsObj = new JSONObject(resultString);
                JSONArray itemsArray = itemsObj.getJSONArray("items");

                // Required to clear list
                if (itemsArray.length() > 0)
                    titles.clear();

                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");

                    // Add to list
                    titles.add(new Video(title, thumbnailUrl, description,videoId));

                    // Update RecyclerView
                    adapter.notifyDataSetChanged();

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

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

            return null;
        }
    }

}

希望这会有所帮助〜

答案 1 :(得分:0)

如果您想简化简单REST调用的代码。您可以使用此库Android RESTAdapter

使用和减少代码非常简单。