[英]ReyclerView. Police Data Json - No adapter attached, skipping layout
[英]How to send multiple Json request and populate ReyclerView with the data
我正在練習為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];
}
};
}
帖子列表的一部分
...
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());
}
我的解決方案存在的問題是所有帖子標題都相同。 為了進一步說明,作者名稱是他們應該使用的名稱,但是所有帖子標題都是最后一篇帖子的標題。
請知道我該如何解決?
應用克里斯·拉森的答案后
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抱怨“無法解析方法getAuthor(Java.lang.String)
從adapter.setPostItems(mPostItemsList);
行adapter.setPostItems(mPostItemsList);
無法解析method'setPostItems(java.util.List.com.example.postapp.PostItems>)'
從adapter.putAuthor(href, authorname);
無法解析方法'putAuthor(java.lang.String)'
在PostAdapter中
從mAuthorMap = new HashMap<>();
“未知類mAuthorMap”,以及在>
位置中應有的 Identifier expected
方法setPostItems
, putAuthor
和getAuthor
都說*方法從未使用過。
在parseAuthor
方法中,我並不太了解您要執行的操作,就好像您要獲取"self"
數組一樣。 雖然我想要的是author數組。
如果您使用的是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-> _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.