简体   繁体   English

如何发送多个Json请求并使用数据填充ReyclerView

[英]How to send multiple Json request and populate ReyclerView with the data

I am practicing building an android app for wordpress blog and what I basically want to do is to fetech the post title and it's author. 我正在练习为wordpress博客构建一个android应用程序,而我基本上想要做的是fetech帖子标题及其作者。 I am able to get and display the post title without any hassles but what's giving headache is the post author. 我能够毫不费力地获得并显示帖子标题,但令人头痛的是帖子作者。

This is the link of the json https://hmn.md/wp-json/wp/v2/posts 这是json https://hmn.md/wp-json/wp/v2/posts的链接

This are my codes 这是我的密码

PostItems PostItems

public class PostItems implements Parcelable {
    private String post_title;
    private String post_author;

    public String getPost_title() {
        return post_title;
    }

    public void setPost_title(String post_title) {
        this.post_title = post_title;
    }



    public String getPost_author() {
        return post_author;
    }

    public void setPost_author(String post_author) {
        this.post_author = post_author;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.post_title);
        dest.writeString(this.post_author);
    }

    public PostItems() {
    }

    protected PostItems(Parcel in) {
        this.post_title = in.readString();
        this.post_author = in.readString();
    }

    public static final Parcelable.Creator<PostItems> CREATOR = new Parcelable.Creator<PostItems>() {
        @Override
        public PostItems createFromParcel(Parcel source) {
            return new PostItems(source);
        }

        @Override
        public PostItems[] newArray(int size) {
            return new PostItems[size];
        }
    };
}

Part of PostList 帖子列表的一部分

...
private void getData(){
         Log.d(TAG, "getData called");
         final ProDialoFrag dialoFrag = ProDialoFrag.newInstance();
         dialoFrag.show(getFragmentManager(), "fragmentDialog");


         //Creating a json request
         jsonArrayRequest = new JsonArrayRequest(GET_URL,
                 new Response.Listener<JSONArray>() {
                     @Override
                     public void onResponse(JSONArray response) {
                         Log.d(TAG, "onResponse called");
                         //Dismissing the progress dialog
                         if (dialoFrag != null ) {
                             dialoFrag.dismiss();
                         }
                         //calling method to parse json array
                         parseData(response);

                     }
                 },
                 new Response.ErrorListener() {
                     @Override
                     public void onErrorResponse(VolleyError error) {
                         if (dialoFrag != null) {
                             dialoFrag.dismiss();
                         }
                         if (sthWrongAlert != null) {
                             sthWrongAlert.show();
                         }

                     }
                 }) {

         };

         //Creating request queue
         RequestQueue requestQueue = Volley.newRequestQueue(getActivity());

         //Adding request to the queue
         requestQueue.add(jsonArrayRequest);

     }

     //This method will parse json data
     private void parseData(JSONArray array){
         Log.d(TAG, "Parsing array");

         mPostItemsList.clear();


         for(int i = 0; i<array.length(); i++) {
             PostItems postItem = new PostItems();
             JSONObject jsonObject = null;
             try {
                 jsonObject = array.getJSONObject(i);

                 JSONObject postTitle = jsonObject.getJSONObject("title");
                 postItem.setPost_title(postTitle.getString("rendered"));

                 JSONObject links = jsonObject.getJSONObject("_links");
                 JSONArray authorLink = links.getJSONArray("author");
                 String authorhref = authorLink.getJSONObject(0).getString("name")



                 postItem.setPostId(jsonObject.getString("link"));
             } catch (JSONException w) {
                 w.printStackTrace();
                 //Toast.makeText(this, "Error in parsing Json", Toast.LENGTH_LONG).show();
             }

             mPostItemsList.add(postItem);

         }
         adapter.notifyItemRangeChanged(0, adapter.getItemCount());


     }

PostAdapter PostAdapter

      public class PostAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{


     private static Context mContext;


     //List of posts
     private List<PostItems> mPostItems;

     private final int VIEW_ITEM = 0;
     private final int VIEW_PROG = 1;

     private int lastPosition = -1;


    public PostAdapter(List<PostItems> postItems, Context context) {
        super();

        //Getting all posts
        this.mPostItems = postItems;
        this.mContext = context;
    }


     @Override
     public int getItemViewType(int position) {
         if (isPositionItem(position))
             return VIEW_ITEM;
         return VIEW_PROG;
     }

     private boolean isPositionItem(int position) {
        return position != getItemCount()-1;
     }



     @Override
     public RecyclerView.ViewHolder  onCreateViewHolder (ViewGroup parent, int viewType) {
         if (viewType == VIEW_ITEM) {
             View v =  LayoutInflater.from(parent.getContext())
                     .inflate(R.layout.post_summ, parent, false);
             return new CardDetails(v);
         } else if (viewType == VIEW_PROG){
             View v = LayoutInflater.from(parent.getContext())
                     .inflate(R.layout.recyclerfooter, parent, false);
             return new ProgressViewHolder(v);
         }

         return null;
     }



     @Override
     public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

         if (holder instanceof CardDetails) {
             final PostItems postList = mPostItems.get(position);

             ((CardDetails) holder).postTitle.setText(Html.fromHtml(postList.getPost_title()));
             ((CardDetails) holder).postAuthor.setText(postList.getPost_author());


         } else {
             ((ProgressViewHolder) holder).progressBar.setIndeterminate(true);
         }


     }

     @Override
     public int getItemCount(){
         //Return the number of items in the data set
         return mPostItems.size();
     }


     public class CardDetails extends RecyclerView.ViewHolder implements View.OnClickListener {
         public TextView postTitle, postAuthor;

         public CardDetails (final View postView) {
             super(postView);
             postTitle = (TextView) postView.findViewById(R.id.post_title);
             postAuthor = (TextView) postView.findViewById(R.id.post_author);
         }

     }

     public  class ProgressViewHolder extends RecyclerView.ViewHolder{
         ProgressBar progressBar;
         public ProgressViewHolder(View footerView){
             super(footerView);
             progressBar = (ProgressBar) footerView.findViewById(R.id.progress_load);
             progressBar.setVisibility(View.VISIBLE);
         }

     }


 }

My Current Solution 我当前的解决方案

 private void parseData(JSONArray array){
         Log.d(TAG, "Parsing array");


         for(int i = 0; i<array.length(); i++) {
             JSONObject jsonObject;
             try {
                 jsonObject = array.getJSONObject(i);

                 JSONObject postTitle = jsonObject.getJSONObject("title");
                 String postT = postTitle.getString("rendered");
                 mPostTitle = postT;


                 JSONObject links = jsonObject.getJSONObject("_links");
                 JSONArray authorLink = links.getJSONArray("author");
                 authorhref = authorLink.getJSONObject(0).getString("href");


                 getAuthor();

             } catch (JSONException w) {
                 w.printStackTrace();
                 //Toast.makeText(this, "Error in parsing Json", Toast.LENGTH_LONG).show();
             }

         }


     }

     private void getAuthor() {
         Log.d(TAG, "getAuthor called");

         JsonObjectRequest authorRequest = new JsonObjectRequest(authorhref, null,
                 new Response.Listener<JSONObject>() {
                     @Override
                     public void onResponse(JSONObject response) {
                         Log.d(TAG, "onResponse called");
                         parseAuthor(response);
                     }
                 },
                 new Response.ErrorListener() {

                     @Override
                     public void onErrorResponse(VolleyError error) {

                     }
                 });

         authorRequest.setShouldCache(false);

         RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
         requestQueue.add(authorRequest);

     }

     private void parseAuthor (JSONObject object) {
         Log.d(TAG, "Parsing author");
         PostItems postItem = new PostItems();

         try {
             String authorname = object.getString("name");
             postItem.setPost_author(authorname);
             postItem.setPost_title(mPostTitle);
         } catch (JSONException w) {
             w.printStackTrace();
         }
         mPostItemsList.add(postItem);
         adapter.notifyItemRangeChanged(0, adapter.getItemCount());
     }

The problem wih my solution is that all the posts titles are the same. 我的解决方案存在的问题是所有帖子标题都相同。 To explain further, the author names are what they are supposed to be, but all the post titles are the title of the last post. 为了进一步说明,作者名称是他们应该使用的名称,但是所有帖子标题都是最后一篇帖子的标题。

Please do have any idea how I could fix this? 请知道我该如何解决?


After Applying kris larson's Answer 应用克里斯·拉森的答案后

Part of PostFragment PostFragment的一部分

public class PostFragment extends Fragment{

    private List<PostItems> mPostItemsList = new ArrayList<>();
    ...
    // Nothing changed here, just added it so you will understand my code better
    ObservableRecyclerView recyclerView;
        private RecyclerView.Adapter adapter;
        LinearLayoutManager mLayoutManager;


        public PostFragment() {
            // Required empty public constructor
        }


        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            String title = getArguments().getString("title");
            // Inflate the layout for this fragment
            view = inflater.inflate(R.layout.fragment_post, container, false);
            //Initializing Views
            recyclerView = (ObservableRecyclerView) view.findViewById(R.id.post_recycler);
            recyclerView.setScrollViewCallbacks(this);
            mLayoutManager = new LinearLayoutManager(getActivity());
            recyclerView.setLayoutManager( mLayoutManager);
            ...

    //This method will get data from the web api
        private void getData(){
            Log.d(TAG, "getData called");
            final ProDialoFrag dialoFrag = ProDialoFrag.newInstance();
            dialoFrag.show(getFragmentManager(), "fragmentDialog");


            //Creating a json request
            jsonArrayRequest = new JsonArrayRequest(GET_URL,
                    new Response.Listener<JSONArray>() {
                        @Override
                        public void onResponse(JSONArray response) {
                            Log.d(TAG, "onResponse called");
                            //Dismissing the progress dialog
                            if (dialoFrag == null ) {
                                dialoFrag.dismiss();
                            }
                            //calling method to parse json array
                            parseData(response);

                        }
                    },
                    new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error) {
                            if (dialoFrag != null) {
                                dialoFrag.dismiss();
                            }
                            if (sthWrongAlert != null) {
                                sthWrongAlert.show();
                            }

                        }
                    }) {
                n Response.success(resp.result, entry);
                }
            };

            //Creating request queue
            RequestQueue requestQueue = Volley.newRequestQueue(getActivity());

            //Adding request to the queue
            requestQueue.add(jsonArrayRequest);

        }

        //This method will parse json data
        private void parseData(JSONArray array){
            Log.d(TAG, "Parsing array");

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

                JSONObject jsonObject;
                try {
                    jsonObject = array.getJSONObject(i);

                    JSONObject postTitle = jsonObject.getJSONObject("title");
                    String title = postTitle.getString("rendered"));

                    JSONObject links = jsonObject.getJSONObject("_links");
                    JSONArray authorLink = links.getJSONArray("author");
                    String authorhref = authorLink.getJSONObject(0).getString("href");

                    PostItems postItem = new PostItems();
                    postItem.setPost_title(title);
                    postItem.setPostAuthorUrl(authorhref);
                    mPostItemsList.add(postItem);

                    if (adapter.getAuthor(authorhref) == null) {
                        getAuthor(authorhref);
                    }
                } catch (JSONException w) {
                    w.printStackTrace();
                    //Toast.makeText(this, "Error in parsing Json", Toast.LENGTH_LONG).show();
                }



            }
            adapter.setPostItems(mPostItemsList);


        }

        private void getAuthor (String authorhref) {
            Log.d(TAG, "getAuthor called");

            JsonObjectRequest authorRequest = new JsonObjectRequest(authorhref, null,
                    new Response.Listener<JSONObject>() {
                        @Override
                        public void onResponse(JSONObject response) {
                            Log.d(TAG, "onResponse called");
                            parseAuthor(response);
                        }
                    },
                    new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error) {
                            //Do nothing
                        }
                    });
            authorRequest.setShouldCache(false);
            RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
            requestQueue.add(authorRequest);
        }
        private void parseAuthor (JSONObject object) {
            Log.d(TAG, "Parsing auhor");
            try {
                JSONObject links = object.getJSONObject("_links");
                JSONArray self = links.getJSONArray("self");
                String href = self.getJSONObject(0).getString("href");

                String authorname = object.getString("name");
                adapter.putAuthor(href, authorname);
            } catch (JSONException w) {
                w.printStackTrace();
            }
        }

}

PostAdapter PostAdapter

public class PostAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{



    private ImageLoader imageLoader;
    private static Context mContext;


    //List of posts
    private List<PostItems> mPostItems;

    //authors by url
    private Map<String, String> mAuthorMap;

    //don't forget to initialoze in adapter constructor
    mAuthorMap = new HashMap<>();

    private final int VIEW_ITEM = 0;
    private final int VIEW_PROG = 1;

    private int lastPosition = -1;

    public void setPostItems(List<PostItems> postItems) {
        mPostItems = postItems;
        notifyDataSetChanged();
    }

    public void putAuthor(String url, String name) {
        mAuthorMap.put(url, name);
        notifyDataSetChanged();
    }

    public String getAuthor(String url) {
        return mAuthorMap.get(url);
    }


   public PostAdapter(List<PostItems> postItems, Context context) {
       super();

       //Getting all posts
       this.mPostItems = postItems;
       this.mContext = context;
   }


    @Override
    public int getItemViewType(int position) {
        if (isPositionItem(position))
            return VIEW_ITEM;
        return VIEW_PROG;
    }

    private boolean isPositionItem(int position) {
       return position != getItemCount()-1;
    }



    @Override
    public RecyclerView.ViewHolder  onCreateViewHolder (ViewGroup parent, int viewType) {
        if (viewType == VIEW_ITEM) {
            View v =  LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.post_summ, parent, false);
            return new CardDetails(v);
        } else if (viewType == VIEW_PROG){
            View v = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.recyclerfooter, parent, false);
            return new ProgressViewHolder(v);
        }

        return null;
    }



    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

        if (holder instanceof CardDetails) {
            final PostItems postList = mPostItems.get(position);
            ((CardDetails) holder).postTitle.setText(Html.fromHtml(postList.getPost_title()));

            String name = mAuthorMap.get(postList.getPostAuthorUrl());
            if (name != null) {
                ((CardDetails) holder).postAuthor.setText(name);
            }

        } else {
            ((ProgressViewHolder) holder).progressBar.setIndeterminate(true);
        }


    }


    @Override
    public int getItemCount(){
        //Return the number of items in the data set
        return mPostItems.size();
    }





    public class CardDetails extends RecyclerView.ViewHolder implements View.OnClickListener {
        public TextView postTitle, postAuthor;
        public ImageButton imageButton;

        public CardDetails (final View postView) {
            super(postView);
            postTitle = (TextView) postView

            .findViewById(R.id.post_title);
            postAuthor = (TextView) postView.findViewById(R.id.post_author);
        }


    }

    public  class ProgressViewHolder extends RecyclerView.ViewHolder{
        ProgressBar progressBar;
        public ProgressViewHolder(View footerView){
            super(footerView);
            progressBar = (ProgressBar) footerView.findViewById(R.id.progress_load);
            progressBar.setVisibility(View.VISIBLE);
        }

    }


}

Problems I am currently Having 我目前遇到的问题

  1. In PostFragment 在PostFragment中

    From line if (adapter.getAuthor(authorhref) == null) { AS is complaining that "cannot resolve method getAuthor(Java.lang.String) 从行开始, if (adapter.getAuthor(authorhref) == null) { AS抱怨“无法解析方法getAuthor(Java.lang.String)

    From line adapter.setPostItems(mPostItemsList); adapter.setPostItems(mPostItemsList);adapter.setPostItems(mPostItemsList); Cannot resolve meethod 'setPostItems(java.util.List.com.example.postapp.PostItems>)' 无法解析method'setPostItems(java.util.List.com.example.postapp.PostItems>)'

    From line adapter.putAuthor(href, authorname); adapter.putAuthor(href, authorname); Cannot resolve method 'putAuthor(java.lang.String)' 无法解析方法'putAuthor(java.lang.String)'

  2. In PostAdapter 在PostAdapter中

From line mAuthorMap = new HashMap<>(); mAuthorMap = new HashMap<>(); 'Unknown class mAuthorMap' and also Identifier expected in the position of > “未知类mAuthorMap”,以及在>位置中应有的 Identifier expected

Methods setPostItems , putAuthor , getAuthor all saying *Method never used. 方法setPostItemsputAuthorgetAuthor都说*方法从未使用过。

And in parseAuthor method, I didn't really understand what you were trying to do, it's as if you are trying to get the "self" array; parseAuthor方法中,我并不太了解您要执行的操作,就好像您要获取"self"数组一样。 though what I wanted is the author array. 虽然我想要的是author数组。

If you were using HttpURLConnection and AsyncTask , you could make both requests in one background operation and have no problem. 如果您使用的是HttpURLConnectionAsyncTask ,则可以在一个后台操作中发出两个请求,并且没有问题。

But since it looks like you are committed to using Volley, I propose that you use a two-phase approach. 但是,由于您似乎决心使用Volley,因此我建议您使用两阶段方法。 In phase 1 you parse the posts and save the author urls for the post. 在阶段1中,您分析帖子并保存帖子的作者url。 In phase 2, you add the author name to a map indexed by url. 在阶段2中,您将作者姓名添加到由url索引的地图中。

  • Have the PostItem contain the author url instead of the author name: PostItem包含作者网址而不是作者名称:

     public class PostItem implements Parcelable { private String post_title; private String post_author_url; // also change all the getters/setters/parceling etc. } 

    (I made it PostItem -- singular -- because it's not a homogeneous collection of any kind.) (我将其设为PostItem(单数),因为它不是任何种类的同质集合。)

  • Add a Map to your adapter to contain the author names: Map添加到适配器以包含作者名称:

      /** posts, which contain author url */ private List<PostItem> mPostItems; /** authors by url */ private Map<String, String> mAuthorMap; 

    don't forget to initialize the author map in adapter constructor 不要忘记在适配器构造函数中初始化作者映射

     public PostAdapter(List<PostItems> postItems, Context context) { super(); //Getting all posts this.mPostItems = postItems; this.mContext = context; this.mAuthorMap = new HashMap<>(); } 
  • When you receive the posts: 当您收到帖子时:

    1. Parse the post item 解析发布项目
    2. Make a PostItem with the title and the author url 使用标题和作者网址制作一个PostItem
    3. Add the PostItem to the adapter PostItem添加到适配器
    4. Ask the adapter for the author 向适配器询问作者
    5. If author not found, start a new author request 如果找不到作者,请发起新的作者请求

        private void parseData(JSONArray array){ Log.d(TAG, "Parsing array"); // Collect all the PostItems and add to adapter all at once List<PostItem> postItems = new ArrayList<>(); for (int i = 0; i<array.length(); i++) { JSONObject jsonObject; try { jsonObject = array.getJSONObject(i); JSONObject postTitle = jsonObject.getJSONObject("title"); String title = postTitle.getString("rendered"); JSONObject links = jsonObject.getJSONObject("_links"); JSONArray authorLink = links.getJSONArray("author"); String authorhref = authorLink.getJSONObject(0).getString("href"); PostItem postItem = new PostItem(); postItem.setPostTitle(title); postItem.setPostAuthorUrl(authorhref); postItems.add(postItem); if (mAdapter.getAuthor(authorhref) == null) { getAuthor(authorhref); } } catch (JSONException w) { w.printStackTrace(); //Toast.makeText(this, "Error in parsing Json", Toast.LENGTH_LONG).show(); } } mAdapter.setPostItems(postItems); } 
  • Notice I changed your getAuthor method to take a parameter (and not use a member variable): 注意,我将您的getAuthor方法更改为采用一个参数(而不使用成员变量):

      private void getAuthor(String authorhref) { ... 
  • When you receive the author, add it to the adapter 收到作者后,将其添加到适配器

      private void parseAuthor (JSONObject object) { Log.d(TAG, "Parsing author"); try { JSONObject links = jsonObject.getJSONObject("_links"); JSONArray self = links.getJSONArray("self"); String href = authorLink.getJSONObject(0).getString("href"); String authorname = object.getString("name"); mAdapter.putAuthor(href, name); } catch (JSONException w) { w.printStackTrace(); } } 
  • Now here are the new adapter methods: 现在,这里是新的适配器方法:

      public void setPostItems(List<PostItem> postItems) { mPostItems = postItems; notifyDataSetChanged(); } public void putAuthor(String url, String name) { mAuthorMap.put(url, name); notifyDataSetChanged(); } public String getAuthor(String url) { return mAuthorMap.get(url); } 
  • And onBindViewHolder is where it all comes together: onBindViewHolder就是它们的结合之处:

      @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (holder instanceof CardDetails) { final PostItem postItem = mPostItems.get(position); ((CardDetails) holder).postTitle.setText(Html.fromHtml(postItem.getPostTitle())); String name = mAuthorMap.get(postItem.getPostAuthorUrl()); if (name != null) { ((CardDetails) holder).postAuthor.setText(name); } // don't worry if author name is null, when it's retrieved // the adapter will be notified to refresh the list } else { ((ProgressViewHolder) holder).progressBar.setIndeterminate(true); } } 

EDIT: Different way to get the author url without having to parse author JSON -> _links -> self[0] -> href 编辑:以多种方式获取作者网址,而无需解析作者JSON-> _links-> self [0]-> href

        // notice that authorhref is final
        private void getAuthor (final String authorhref) {
            Log.d(TAG, "getAuthor called");

            JsonObjectRequest authorRequest = new JsonObjectRequest(authorhref, null,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        Log.d(TAG, "onResponse called");
                        parseAuthor(authorhref, response);  // pass authorhref with response
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        //Do nothing
                    }
                });
                authorRequest.setShouldCache(false);
                RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
                requestQueue.add(authorRequest);
            }

            private void parseAuthor (String authorhref, JSONObject object) {

                Log.d(TAG, "Parsing author");
                try {
                    String authorname = object.getString("name");
                    mAdapter.putAuthor(authorhref, name);

                } catch (JSONException w) {
                    w.printStackTrace();
                }

            }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM