Im facing issues with RecyclerViewAdapter
Following is my error :
java.lang.NullPointerException: Attempt to invoke virtual method 'void
android.support.v7.widget.RecyclerView.setLayoutManager(android.support.v7.widget.RecyclerView$LayoutManager)'
on line :
recyclerView.setLayoutManager(mLayoutManager);
I set adapter recyclerview when fragment is create and when user click an item in recyclerview , it calls api to update this recyclerview but problem is when user click item above exception occurs
How to fix it
Following is my code :
recyclerView = (RecyclerView) lay_custom_center_post_topic.findViewById(R.id.lv_poll_feed);
AdapDetailTopicPoll adapDetailTopicPoll = new AdapDetailTopicPoll(timelineFeedListModels.get(i).getPost().getPoll());
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapDetailTopicPoll);
adapDetailTopicPoll.notifyDataSetChanged();
new_position = i;
public void sendVodePoll(final int position, String poll_id,final int new_position, final List<ProfileFeedListModelTwo.PostBean.PollBean> poll) {
RequestParams params = new RequestParams();
String URL = "xxxx/xx";
params.put("poll_id", poll_id);
AsyncHttpClient client = new AsyncHttpClient();
client.post(URL, params, new JsonHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, JSONArray response) {
ArrayList<ProfileFeedListModelTwo.PostBean.PollBean> pollBeanArrayList = new ArrayList<ProfileFeedListModelTwo.PostBean.PollBean>();
StringBuilder result = new StringBuilder();
String vote = null;
String poll_id=null;
String status_vote=null;
Gson gson = new Gson();
try {
List<TopicVoteModel> topicVoteModels = new ArrayList<>();
for (int i=0 ; i<response.length() ; i++){
JSONObject jsonObject = response.getJSONObject(i);
vote = jsonObject.getString("vote");
topicVoteModels.add(gson.fromJson(String.valueOf(jsonObject), TopicVoteModel.class));
}
boolean new_status_vote = Boolean.parseBoolean(status_vote);
poll.get(position).setVote(Integer.parseInt(vote));
poll.get(position).setStatus_vote(new_status_vote);
for (ProfileFeedListModelTwo.PostBean.PollBean pollBean : poll){
pollBeanArrayList.add(pollBean);
}
adapDetailTopicPoll = new AdapDetailTopicPoll(pollBeanArrayList, context);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(mLayoutManager); //inline this error
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapDetailTopicPoll);
adapDetailTopicPoll.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
adapter
public class AdapDetailTopicPoll extends RecyclerView.Adapter<AdapDetailTopicPoll.MyViewHolder> {
SearchDetailFragment searchDetailFragment = new SearchDetailFragment();
Context context;
private List<ProfileFeedListModelTwo.PostBean.PollBean> poll = new ArrayList<ProfileFeedListModelTwo.PostBean.PollBean>();
public AdapDetailTopicPoll( List<ProfileFeedListModelTwo.PostBean.PollBean> poll ,Context context){
this.poll = poll;
this.context=context;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.custom_profile_feed_topic_poll,parent,false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
holder.tx_poll.setText(""+poll.get(position).getName());
if (poll.get(position).isStatus_vote()==false){
holder.img_vote.setImageResource(R.drawable.vote_t_1);
holder.tx_count_vote.setText(""+poll.get(position).getVote());
}else {
holder.img_vote.setImageResource(R.drawable.vote_t_2);
holder.tx_count_vote.setText(""+poll.get(position).getVote());
}
}
#Override
public int getItemCount() {
return poll.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView tx_poll,tx_count_vote;
public ImageView img_vote;
public MyViewHolder(View view) {
super(view);
tx_poll = (TextView) view.findViewById(R.id.tx_poll);
tx_count_vote = (TextView) view.findViewById(R.id.tx_count_vote);
img_vote = (ImageView) view.findViewById(R.id.img_vote);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ProfileFragment.poll_id = String.valueOf(poll.get(getAdapterPosition()).getId());
searchDetailFragment.sendVodePoll(getAdapterPosition(),ProfileFragment.poll_id,SearchDetailFragment.new_position,poll);
}
});
}
}
}
Write these lines directly in onCreate() method of the activity
adapDetailTopicPoll = new AdapDetailTopicPoll(pollBeanArrayList, context);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapDetailTopicPoll);
and initialize the adapter and arraylist as the global variable.
In RecyclerView there are 2 ways that are commonly used - In the form of a List or in the form of a Grid. So for list formation you'll provide a layout manager like this -
LinearLayoutManager layoutManagerFuture = new LinearLayoutManager(context);
layoutManagerFuture.setOrientation(LinearLayoutManager.VERTICAL);
and for Grid formation
GridLayoutManager layoutManager = new GridLayoutManager(context, totalItemsInOneRow);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
Related
i want create a fragment and have inside a recycler view for show products ...
but when i render it is show this error : RecyclerView: No adapter attached; skipping layout
below i copy my codes;
this code is for adapter class :
private ArrayList<Products> ProductsList;
private Context context;
public Adapter(ArrayList<Products> productsList, Context context) {
ProductsList = productsList;
this.context = context;
}
#Override
public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.row_layout, parent, false);
return new MyHolder(v);
}
#Override
public void onBindViewHolder(MyHolder holder, final int position) {
Products products = ProductsList.get(position);
holder.txtName.setText(products.getName());
holder.txtPrice.setText("$ " + products.getPrice());
Picasso.get().load(Config.ipValue + "/images/" + products.getPhoto()).into(holder.imgV);
holder.imgV.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
v.startAnimation(AnimationUtils.loadAnimation(context, android
.R.anim.slide_in_left));
}
});
}
#Override
public int getItemCount() {
return ProductsList.size();
}
class MyHolder extends RecyclerView.ViewHolder {
TextView txtName;
TextView txtPrice;
ImageView imgV;
public MyHolder(View itemView) {
super(itemView);
txtName = itemView.findViewById(R.id.rowTxtProductName);
txtPrice = itemView.findViewById(R.id.rowTxtPrice);
imgV = itemView.findViewById(R.id.rowImgProduct);
}
}
and this one for web api class :
public class WebApiHandler {
Context context;
String apiLink = "";
ArrayList<Products> products = new ArrayList<>();
public WebApiHandler(Context context) {
this.context = context;
}
void apiConnect(String type) {
switch (type) {
case "getproducts": {
apiLink = Config.getProductsWebApi;
break;
}
}
ProgressDialog dialog = ProgressDialog.show(context, "Connecting...",
"please wait", false, false);
StringRequest request = new StringRequest(Request.Method.POST,
apiLink, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
dialog.dismiss();
showJson(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
dialog.dismiss();
}
});
RequestQueue queue = Volley.newRequestQueue(context);
queue.add(request);
}
private void showJson(String response) {
products.clear();
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray jsonArray = jsonObject.getJSONArray("response");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject object = jsonArray.getJSONObject(i);
String id = object.getString("id");
String name = object.getString("name");
String description = object.getString("description");
String price = object.getString("price");
String photo = object.getString("photo");
Products p = new Products(id, name, description, price, photo);
products.add(p);
}
} catch (JSONException e) {
e.printStackTrace();
}
VerticalFragment.productsArrayList = products;
IData iData = (IData) context;
iData.sendData();
}}
and my fragment code :
public class VerticalFragment extends Fragment implements IData {
RecyclerView rcVertical;
WebApiHandler webApiHandler;
static ArrayList<Products> productsArrayList = new ArrayList<>();
public VerticalFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_vertical, container, false);
rcVertical = view.findViewById(R.id.rcVertical);
webApiHandler = new WebApiHandler(getContext());
webApiHandler.apiConnect("getproducts");
rcVertical.addOnItemTouchListener(new RecyclerTouchListener(getContext(), rcVertical,
new RecyclerTouchListener.ClickListener() {
#Override
public void onClick(View view, int position) {
ProductActivity.products = productsArrayList.get(position);
startActivity(new Intent(getContext(), ProductActivity.class));
}
#Override
public void onLongClick(View view, int position) {
}
}));
return view;
}
#Override
public void sendData() {
Adapter adapter = new Adapter(productsArrayList, getContext());
rcVertical.setLayoutManager(new LinearLayoutManager((getContext())));
rcVertical.setItemAnimator(new DefaultItemAnimator());
rcVertical.setAdapter(adapter);
}}
i should say i create a interface and have one method i say it sendData
This is a common error when there is no adapter attached to recyclerview upon showing recyclerview. It will not cause any harm to your app, but you could avoid it by setting empty adapter without data, and later when you get your data, provide it to your adapter and notify it
Edit - Example added
Create setter for your list in adapter. After that, in your fragment make adapter global and in onCreateView make instance of your adapter and attach it to recyclerview
adapter = new Adapter(new ArrayList<>(), getContext());
rcVertical.setAdapter(adapter);
...Initialize recyclerview...
And then in your sendData interface put your loaded values in it
adapter.setData(productsArrayList);
adapter.notifyDataSetChanged();
I am new to android, developing an android application but I stuck here. RecyclerView shows empty. There are no errors or crashes in the log. I deleted and created new but same issue. I cant find what's wrong.
java code for main activity
public class HomeActivity extends AppCompatActivity {
private RecyclerView rcview1;
private RecyclerView.Adapter cmpadapter1;
private List<commdtylist> listitems2;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
rcview1 = (RecyclerView) findViewById(R.id.commoditylist);
rcview1.setItemAnimator(new DefaultItemAnimator());
listitems2 = new ArrayList<>();
rcview1.setHasFixedSize(true);
viewcmp();
}
public void viewcmp() {
StringRequest stringRequest=new StringRequest(Request.Method.POST, otpur, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jobj = new JSONObject(response);
JSONArray jsonArray = jobj.getJSONArray("Details");
for (int i = 0; i < jsonArray.length(); i++) {
jobj = jsonArray.getJSONObject(i);
commdtylist item = new commdtylist(
jobj.getString("quantity_entitle"),
jobj.getString("comm_code"),
jobj.getString("item_description")
);
listitems2.add(item);
}
cmpadapter1 = new CommdityviewAdapter(listitems2, getApplicationContext());
rcview1.setAdapter(cmpadapter1);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> param = new HashMap<>();
param.put("rc_no", crd);
return param;
}
};
RequestQueue requestQueue= Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
commdtylist
public class commdtylist {
private String quantity_entitle;
private String comm_code;
private String item_description;
public commdtylist(String quantity_entitle, String comm_code, String item_description) {
this.quantity_entitle = quantity_entitle;
this.comm_code = comm_code;
this.item_description = item_description;
}
public String getquantity_entitle() {
return quantity_entitle;
}
public String getcomm_code() {
return comm_code;
}
public String getitem_description() {
return item_description;
}
}
Adapter
public class CommdityviewAdapter extends RecyclerView.Adapter<CommdityviewAdapter.RViewHolder> {
private List<commdtylist> listitems2;
private Context context;
int lastPosition = -1;
public CommdityviewAdapter(List<commdtylist> listitems2, Context context) {
this.listitems2 = listitems2;
this.context = context;
}
public static Toast t = null;
#Override
public RViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v= LayoutInflater.from(parent.getContext()).inflate(R.layout.view_cmdstyle,parent,false);
return new RViewHolder(v);
}
#Override
public void onBindViewHolder(final RViewHolder holder,final int position) {
final commdtylist listitem=listitems2.get(position);
holder.quantity_entitle.setText(listitem.getquantity_entitle());
holder.comm_code.setText(listitem.getcomm_code());
holder.item_description.setText(listitem.getitem_description());
setAnimation(holder.itemView, position);
}
private void setAnimation(View itemView, int position) {
// If the bound view wasn't previously displayed on screen, it's animated
if (position > lastPosition)
{
Animation animation = AnimationUtils.loadAnimation(itemView.getContext(), R.anim.up_from_bottom);
itemView.startAnimation(animation);
lastPosition = position;
}
else{
Animation animation = AnimationUtils.loadAnimation(itemView.getContext(), R.anim.down_from_top);
//android.R.anim.slide_in_left
itemView.startAnimation(animation);
lastPosition = position;
}
}
#Override
public int getItemCount() {
return listitems2.size();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
public class RViewHolder extends RecyclerView.ViewHolder{
public TextView quantity_entitle,comm_code,item_description;
public RViewHolder(View itemView) {
super(itemView);
quantity_entitle=(TextView)itemView.findViewById(R.id.quantity_entitle);
comm_code=(TextView)itemView.findViewById(R.id.comm_code);
item_description=(TextView)itemView.findViewById(R.id.item_description);
}
}
}
You have to add LayoutManager to RecyclerView . Use setLayoutManager (RecyclerView.LayoutManager layout) method to set LayoutManager to RecyclerView. If you don't set any LayoutManager you will not see any data.
LinearLayoutManager manager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(manager);
final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerview.setLayoutManager(layoutManager);
Hope to help you.
Please set RecyclerView's layoutmanager with setLayoutManager method.
Set the layout manager to the recylerView
rcview1.setAdapter(cmpadapter1);
rcview1.setLayoutManager(new LinearLayoutManager(this));
make some change in home activity like
private CommdityviewAdapter cmpadapter1; // replace private RecyclerView.Adapter cmpadapter1;
rcview1.setLayoutManager(new LinearLayoutManager(this));
and when you set the adapter in recyclerview then after notifiy to adapter.
cmpadapter1.notifyDataSetChanged();
I have been reading the different answers here on stackoverflow and tried to implement their solutions but I am still getting the error:
RecyclerView: No adapter attached; skipping layout
I have spent days on trying to troubleshoot but no luck any help will be appreciated.
public class GaneshMainActivity extends AppCompatActivity {
private static final String URL_DATA = "https://mantraapp.000webhostapp.com/tag/ganesh-mantra?json=1";
private RecyclerView recyclerView;
private GaneshMyAdapter adapter;
private List < GaneshListitem > ganeshListitem;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ganesh_mantra);
recyclerView = (RecyclerView) findViewById(R.id.ganesh_recyclerview);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
ganeshListitem = new ArrayList < > ();
load_data_from_server();
}
private void load_data_from_server() {
StringRequest stringRequest = new StringRequest(Request.Method.GET,
URL_DATA,
new Response.Listener < String > () {
#Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray array = jsonObject.getJSONArray("Ganesha Mantra");
for (int i = 0; i < array.length(); i++) {
JSONObject object = array.getJSONObject(i);
GaneshListitem data = new GaneshListitem(
object.getString("title"),
object.getString("content"),
object.getString("thumbnail")
);
ganeshListitem.add(data);
}
} catch (JSONException e) {
System.out.println("No content");
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
Toast.makeText(getApplicationContext(), volleyError.getMessage(), Toast.LENGTH_LONG).show();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
}
I am not sure what I am doing wrong below is GaneshMyadpater.java file
public class GaneshMyAdapter extends RecyclerView.Adapter < GaneshMyAdapter.ViewHolder > {
private List < GaneshListitem > GaneshlistItems;
private Context context;
public GaneshMyAdapter(Context context, List < GaneshListitem > my_data) {
this.context = context;
this.GaneshlistItems = my_data;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.listitem, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.title.setText(GaneshlistItems.get(position).getHead());
holder.content.setText(GaneshlistItems.get(position).getDesc());
}
#Override
public int getItemCount() {
return GaneshlistItems.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView title;
public TextView content;
public ImageView thumbnail;
public ViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.textviewHead);
content = (TextView) itemView.findViewById(R.id.textviewDesc);
thumbnail = (ImageView) itemView.findViewById(R.id.thumbnail);
}
}
}
Add this line in your onCreate
adapter = new GaneshAdapter(this , ganeshListitem);
recyclerView.setAdapter(adapter);
and call notifyDataSetChanged() when items are added in your list
adapter.notifyDataSetChanged();
this will update the recycleview with new data
ganeshListitem = new ArrayList < > ();
adapter = new GaneshAdapter(this , ganeshListitem);
recyclerView.setAdapter(adapter);
load_data_from_server();
make above changes at onCreate()
adapter.addData(ganeshListitem)
Add above line after ganeshListitem.add(data);
public void addData(List<GaneshListitem> list){
GaneshlistItems.addAll(list);
notifyDataSetChanged()
}
Add this above method to your adapter class
You need to implement like this
you have to take arrayList type hashmap and initialise them ArrayList<HashMap<String,String>> allValues=new ArrayList<>();
then you've to put your response values in your hashmap like this
add this in your oncreate
context = getActivity();
RecyclerView.LayoutManager recyclerViewLayoutManager = new LinearLayoutManager(context);
rv_lunch_break.setLayoutManager(recyclerViewLayoutManager);
private void load_data_from_server() {
StringRequest stringRequest = new StringRequest(Request.Method.GET,
URL_DATA,
new Response.Listener < String > () {
#Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray array = jsonObject.getJSONArray("Ganesha Mantra");
for (int i = 0; i < array.length(); i++) {
JSONObject object = array.getJSONObject(i);
HashMap<String,String> hashMap=new HashMap<>();
hashMap.put("title",object.getString("title"));
hashMap.put("content",object.getString("content"));
hashMap.put("thumbnail",object.getString("thumbnail"));
allValues.add(hashMap);
adapter=new yourAdapterName(context,allValues);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
} catch (JSONException e) {
System.out.println("No content");
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
Toast.makeText(getApplicationContext(),
volleyError.getMessage(), Toast.LENGTH_LONG).show();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
In your adapter class you have to take again arrayList type hashmap and hashmap and also initialise them also like this
HashMap<String,String> hashMAp=new HashMap<>();
private ArrayList<HashMap<String,String>> allList;
In your onBindViewHolder you need to extract value like this
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
hashMAp=allList.get(position);
holder.your_TextView_Refrence.setText(hashmap.get("title"));
holder.your_TextView_Refrence.setText(hashmap.get("content"));
}
Happy to help you
Add this code below “
recyclerView.setLayoutManager(new LinearLayoutManager(this));
” :
recycleView. setAdapter(adapter);
And add this code below “
JSONObject jsonObject = new JSONObject(response);
JSONArray array = jsonObject.getJSONArray("Ganesha Mantra");
for (int i = 0; 1 < array.length(); i++) {
JSONObject object = array.getJSONObject(i);
GaneshListitem data = new GaneshListitem(
object.getString("title"),
object.getString("content"),
object.getString("thumbnail")
);
ganeshListitem.add(data);
}
”:
adapter. notifyDataSetChanged();
I am using a loader and a OkHttp client to get data from a news API and populate the data in a recycler view. I used a progress bar to show until the the loader is finished loading the data . But all I see is the progress bar, the recycler view is not showing up.
Please help me
MainActivity.java
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<ArrayList<News>> {
private static final int LOADER_ID = 1 ;
private String url = "https://newsapi.org/v1/articles?source=the-times-of-india&sortBy=latest&apiKey=<API KEY>";
private ProgressBar progressBar;
private NewsAdapter mAdapter;
private RecyclerView recList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = (ProgressBar) findViewById(R.id.progress_bar);
progressBar.setVisibility(View.VISIBLE);
recList = (RecyclerView) findViewById(R.id.cardList);
recList.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(this);
llm.setOrientation(LinearLayoutManager.VERTICAL);
recList.setLayoutManager(llm);
recList.setHasFixedSize(true);
getSupportLoaderManager().initLoader(LOADER_ID , null , this);
}
#Override
public Loader<ArrayList<News>> onCreateLoader(int id, Bundle args) {
return new AsyncTaskLoader<ArrayList<News>>(this) {
#Override
public ArrayList<News> loadInBackground() {
return makeConnectionAndParseData(url);
}
};
}
#Override
public void onLoadFinished(Loader<ArrayList<News>> loader, ArrayList<News> data) {
progressBar.setVisibility(View.INVISIBLE);
mAdapter = new NewsAdapter(data);
recList.setAdapter(mAdapter);
// The data is brought back here after the network call is executed in the variable data.
// Update the recycler view here to show the list of news
// Take care of exception cases like no network connection , invalid url and other extreme cases
}
#Override
public void onLoaderReset(Loader<ArrayList<News>> loader) {
// Reset the recycler view . The UI should not show recycler view when the loader is reset
// Update the UI with a text view to let the user know about the error
}
private String makeNetworkConnection(String url)
{
OkHttpClient client = new OkHttpClient();
try {
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.body().toString();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private ArrayList<News> parseJsonIntoArrayList(String json)
{
final ArrayList<News> newsArrayList;
try {
newsArrayList = null;
JSONObject object = new JSONObject(json);
JSONArray articles = object.getJSONArray("articles");
for (int i=0 ; i<articles.length() ; i++)
{
JSONObject articleObjects = articles.getJSONObject(i);
String author = articleObjects.getString("author");
String title = articleObjects.getString("title");
String desc = articleObjects.getString("description");
String imageUrl = articleObjects.getString("imageUrl");
String clickableUrl = articleObjects.getString("url");
newsArrayList.add(new News(title,desc,imageUrl,clickableUrl,author));
}
return newsArrayList;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
private ArrayList<News> makeConnectionAndParseData(String url)
{
String jsonResponse = makeNetworkConnection(url);
return parseJsonIntoArrayList(jsonResponse);
}}
NewsAdapter.java
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.NewsHolder> {
ArrayList<News> mNewsData;
public NewsAdapter(ArrayList<News> newsData)
{
mNewsData = newsData;
}
public class NewsHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView titleTv , descTv ;
private ImageView newsImageView;
public NewsHolder(View itemView) {
super(itemView);
titleTv = (TextView) itemView.findViewById(R.id.newsTitle);
descTv = (TextView) itemView.findViewById(R.id.newsDesc);
newsImageView = (ImageView) itemView.findViewById(R.id.newsImage);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
// Handle the click item here.
}
}
#Override
public NewsHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View inflatedView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item , parent , false);
return new NewsHolder(inflatedView);
}
#Override
public void onBindViewHolder(NewsHolder holder, int position) {
News news = mNewsData.get(position);
holder.titleTv.setText(news.getNewsTitle());
holder.descTv.setText(news.getNewsSubtitle());
String imageUrl = news.getImageUrl();
Picasso.with(holder.newsImageView.getContext())
.load(imageUrl)
.into(holder.newsImageView);
}
#Override
public int getItemCount() {
return mNewsData.size();
}}
In android monitor , there was
01-10 14:55:59.319 10318-10318/com.sriram.news E/RecyclerView: No adapter attached; skipping layout
Please tell me where I have gone wrong
And is my implementation of the recycler view correct? I'm still confused about recycler view.
Thanks in advance
Place
mAdapter = new NewsAdapter();
recList.setAdapter(mAdapter);
above
recList.setLayoutManager(llm);
recList.setHasFixedSize(true);
and fix NewsAdapter.java
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.NewsHolder> {
ArrayList<News> mNewsData;
// remove constructor
public void addAll(List<News> newsData) {
mNewsData = newsData;
}
...
}
MainActivity.java
#Override
public void onLoadFinished(Loader<ArrayList<News>> loader, ArrayList<News> data) {
progressBar.setVisibility(View.INVISIBLE);
mAdapter.addAll(data);
mAdapter.notifyDataSetChanged();
}
This is a follow-up to my previous question: Parse RecyclerView Image Query
I am now having a paradoxical nullpointer exception. I am attempting to extract a list from an inner method, in the way outlined below.
public List<ParseObject> objectList;
public List<String> getData(String filter){
ParseQuery<ParseObject> query = ParseQuery.getQuery("Images");
query.whereEqualTo("category", filter);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> downloads, com.parse.ParseException e) {
if (e == null) {
objectList=downloads;
} else {
Log.d("score", "Error: " + e.getMessage());
}
}
});
int size = objectList.size();
for (int i = 0; i<size; i++){
ParseFile file = (ParseFile) objectList.get(i).get("Image");
urlList.add(file.getUrl());
}
return urlList;
}
How do I solve this? What ways exist which are better than what I am using?
EDIT:
Here is what it's doing. At present there are no exceptions, but the recyclerview is not displaying anything.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_events, container, false);
setList("sport", rootView);
return rootView;
}
public void set() {
}
public void setList(String filter, View view){
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.rv);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(linearLayoutManager);
MyAdapter myAdapter = new MyAdapter(getData(filter));
recyclerView.setAdapter(myAdapter);
}
EDIT 2: More updated code:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_events, container, false);
setList("sport", rootView);
return rootView;
}
public void set() {
}
public void setList(String filter, View view){
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.rv);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(linearLayoutManager);
MyAdapter myAdapter = new MyAdapter(getData(filter));
recyclerView.setAdapter(myAdapter);
}
private List<String> urlList = new ArrayList<>();
public List<ParseObject> objectList = new ArrayList<>();
public int size;
public List<String> getData(String filter){
ParseQuery<ParseObject> query = ParseQuery.getQuery("Images");
query.whereEqualTo("category", filter);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> downloads, com.parse.ParseException e) {
if (e == null) {
Toast.makeText(getActivity(), "Downloads retrieved", Toast.LENGTH_SHORT).show();
objectList.addAll(downloads);
} else {
Log.d("score", "Error: " + e.getMessage());
}
size = objectList.size();
}
});
for (int i = 0; i<size; i++){
ParseFile file = (ParseFile) objectList.get(i).get("Image");
urlList.add(file.getUrl());
}
return urlList;
}
EDIT 3: Updated, and I have added my adapter code.
View rootView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.activity_events, container, false);
new GetUrlListTask(this).execute("sport");
return rootView;
}
public void set() {
}
private List<String> urlList = new ArrayList<>();
public List<ParseObject> objectList = new ArrayList<>();
public int size;
public List<String> getData(String filter){
ParseQuery<ParseObject> query = ParseQuery.getQuery("Images");
query.whereEqualTo("category", filter);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> downloads, com.parse.ParseException e) {
if (e == null) {
Toast.makeText(getActivity(), "Downloads retrieved", Toast.LENGTH_SHORT).show();
objectList.addAll(downloads);
} else {
}
size = objectList.size();
}
});
for (int i = 0; i<size; i++){
ParseFile file = (ParseFile) objectList.get(i).get("Image");
urlList.add(file.getUrl());
}
return urlList;
}
private class GetUrlListTask extends AsyncTask<String,Void,List<String>>
{
private WeakReference<Fragment> weakRef;
public GetUrlListTask(Fragment frag){
weakRef = new WeakReference< Fragment >(frag);
}
#Override
protected List<String> doInBackground(String... filters) {
return getData(filters[0]);
}
#Override
protected void onPostExecute(List<String> urlList) {
Fragment frag = weakRef.get();
if (frag != null){
RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.rv);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(linearLayoutManager);
MyAdapter myAdapter = new MyAdapter(urlList);
recyclerView.setAdapter(myAdapter);
}
}
}
And My adapter:
List<String> urls;
ViewGroup parent;
public MyAdapter(List<String> urls){
this.urls=urls;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.image_entry, parent);
MyViewHolder myViewHolder = new MyViewHolder(view);
this.parent=parent;
return myViewHolder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Picasso.with(parent.getContext())
.load(urls.get(position))
.into(holder.photo);
Toast.makeText(parent.getContext(), urls.get(position), Toast.LENGTH_LONG).show();
}
#Override
public int getItemCount() {
return urls.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder{
ImageView photo;
public MyViewHolder(View itemView) {
super(itemView);
photo = (ImageView) itemView.findViewById(R.id.listImage);
}
}
So I am assuming that what you want to do is once you get the urlList, you want to update some view. If that's the case then I think what you want to do it run that whole method in a background task rather than just the query like so:
First change your getData() method:
public List<String> getData(String filter){
ParseQuery<ParseObject> query = ParseQuery.getQuery("Images");
query.whereEqualTo("category", filter);
objectList = query.find(); //I think you have to surround this by a try catch or have the method throw an exception
int size = objectList.size();
for (int i = 0; i<size; i++){
ParseFile file = (ParseFile) objectList.get(i).get("Image");
urlList.add(file.getUrl());
}
return urlList;
}
Note that since you are doing a network call, the above method now HAS to run from a background thread.
Then you can use something like an AsyncTask to update a view:
private class GetUrlListTask extends AsyncTask<String,Void,List<String>>
{
private WeakReference<Fragment> weakRef;
public PhotoTagsFetchTask(Fragment frag){
weakRef = new WeakReference< Fragment >(frag);
}
#Override
protected Void doInBackground(String... filters) {
return getData(filters[0]);
}
#Override
protected void onPostExecute(List<String> urlList) {
Fragment frag = weakRef.get();
if (frag != null){
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.rv);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(linearLayoutManager);
MyAdapter myAdapter = new MyAdapter(urlList);
recyclerView.setAdapter(myAdapter);
}
}
}
Note that the use of weak reference above is to avoid context leaks (basically avoids unnecessary memory leaks).
You could also do this:
public void getData(String filter){
ParseQuery<ParseObject> query = ParseQuery.getQuery("Images");
query.whereEqualTo("category", filter);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> downloads, com.parse.ParseException e) {
if (e == null) {
objectList=downloads;
int size = objectList.size();
for (int i = 0; i<size; i++){
ParseFile file = (ParseFile) objectList.get(i).get("Image");
urlList.add(file.getUrl());
}
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.rv);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(linearLayoutManager);
MyAdapter myAdapter = new MyAdapter(urlList);
recyclerView.setAdapter(myAdapter);
} else {
Log.d("score", "Error: " + e.getMessage());
}
}
});
}
Change objectList=downloads to objectList.addAll(downloads) and add objectList = new ArrayList<>() in the first line.
Also move the section starting fromobjectList.size() inside the done method of query callback