我正在练习为wordpress博客构建一个Android应用程序,我基本上想要做的是fetech帖子标题和它的作者。我能够毫无困难地获得并显示帖子标题,但是令人头疼的是帖子的作者。
这是json https://hmn.md/wp-json/wp/v2/posts
的链接这是我的代码
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];
}
};
}
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
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);
}
}
}
我当前的解决方案
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());
}
问题在于我的解决方案是所有帖子都是相同的。为了进一步解释,作者的名字是它们应该是什么,但所有的帖子标题都是最后一篇文章的标题。
请知道如何解决这个问题?
应用kris larson的答案后
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
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);
}
}
}
我目前遇到的问题
在PostFragment中
来自行if (adapter.getAuthor(authorhref) == null) {
AS抱怨&#34;无法解析方法 getAuthor(Java.lang.String)
从第adapter.setPostItems(mPostItemsList);
行无法解析meethod&#39; setPostItems(java.util.List.com.example.postapp.PostItems&gt;)&#39;
从第adapter.putAuthor(href, authorname);
行无法解析方法&#39; putAuthor(java.lang.String)&#39;
在PostAdapter中
来自mAuthorMap = new HashMap<>();
&#39;未知类mAuthorMap&#39; 以及 Identifier expected
位置>
方法setPostItems
,putAuthor
,getAuthor
都说'方法从未使用过。
在parseAuthor
方法中,我并没有真正理解你想要做什么,就好像你想要获得"self"
数组一样;虽然我想要的是作者阵列。
答案 0 :(得分:0)
如果您使用HttpURLConnection
和AsyncTask
,则可以在一次后台操作中同时发出这两个请求,并且没有任何问题。
但是因为看起来你致力于使用Volley,我建议你使用两阶段方法。在阶段1中,您解析帖子并保存帖子的作者URL。在阶段2中,您将作者姓名添加到由url索引的地图中。
让PostItem
包含作者网址而不是作者姓名:
public class PostItem implements Parcelable {
private String post_title;
private String post_author_url;
// also change all the getters/setters/parceling etc.
}
(我把它作为PostItem - 单数 - 因为它不是任何类型的同类集合。)
在适配器中添加Map
以包含作者姓名:
/** posts, which contain author url */
private List<PostItem> mPostItems;
/** authors by url */
private Map<String, String> mAuthorMap;
不要忘记在适配器构造函数中初始化作者地图
public PostAdapter(List<PostItems> postItems, Context context) {
super();
//Getting all posts
this.mPostItems = postItems;
this.mContext = context;
this.mAuthorMap = new HashMap<>();
}
收到帖子时:
PostItem
PostItem
添加到适配器如果找不到作者,请启动新的作者请求
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);
}
注意我更改了getAuthor
方法以获取参数(而不是使用成员变量):
private void getAuthor(String authorhref) {
...
收到作者后,将其添加到适配器
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();
}
}
现在这里是新的适配器方法:
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);
}
而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);
}
}
编辑:获取作者网址的不同方式,而无需解析作者JSON - &gt; _links - &gt;自我[0] - &gt; 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();
}
}