Reputation: 3956
I am fetching news Items from Json using Volley. In the MainActivity I have successfully fetched and parsed the json, so I have no problem with that. Now each news item contains a title and an excerpt of the news. What I wanted was that each time the news excerpt is clicked, it will start another activity called NewsDetails, during the starting, the "ID" (a json object) of the news excerpt clicked, will be sent to NewsDetails.
In NewsDetails I will concatenate the "ID" and the url of the website; this will also return a json array. Then I'll parse the json and display it; hopefully this won't give me a problem.
Where I am experiencing difficulties is trying to send the "ID" and starting the "NewsDetails".
So far this is what I have been doing:
All MainActivity class
public class MainActivity extends AppCompatActivity{
private final String TAG = "MainActivity";
//Creating a list of newss
private List<NewsItems> mNewsItemsList;
//Creating Views
private RecyclerView recyclerView;
private RecyclerView.Adapter adapter;
private ProgressDialog mProgressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "Device rotated and onCreate called");
//Initializing Views
recyclerView = (RecyclerView) findViewById(R.id.news_recycler);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
//Initializing the newslist
mNewsItemsList = new ArrayList<>();
adapter = new NewsAdapter(mNewsItemsList, this);
recyclerView.setAdapter(adapter);
//Caling method to get data
getData();
}
//This method will get data from the web api
private void getData(){
Log.d(TAG, "getData called");
//Showing progress dialog
mProgressDialog = new ProgressDialog(MainActivity.this);
mProgressDialog.setCancelable(false);
mProgressDialog.setMessage(this.getResources().getString(R.string.load_news));
mProgressDialog.show();
//Creating a json request
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(ConfigNews.GET_URL,
new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
Log.d(TAG, "onResponse called");
//Dismissing the progress dialog
if (mProgressDialog != null) {
mProgressDialog.hide();
}
/*progressDialog.dismiss();*/
//calling method to parse json array
parseData(response);
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
//Creating request queue
RequestQueue requestQueue = Volley.newRequestQueue(this);
//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++) {
NewsItems newsItem = new NewsItems();
JSONObject jsonObject = null;
try {
jsonObject = array.getJSONObject(i);
newsItem.setNews_title(jsonObject.getString(ConfigNews.TAG_NEWS_TITLE));
newsItem.setNews_excerpt(jsonObject.getString(ConfigNews.TAG_NEWS_EXCERPT));
newsItem.setNewsId(jsonObject.getInt(ConfigNews.TAG_NEWS_ID));
} catch (JSONException w) {
w.printStackTrace();
}
mNewsItemsList.add(newsItem);
}
adapter.notifyItemRangeChanged(0, adapter.getItemCount());
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy called");
if (mProgressDialog != null){
mProgressDialog.dismiss();
Log.d(TAG, "mProgress dialog dismissed");
}
}
}
No problem from the code above.
The Whole NewsItems class
public class NewsItems {
private String news_title;
private String news_excerpt;
private String news_id;
public String getNews_title() {
return news_title;
}
public void setNews_title(String news_title) {
this.news_title = news_title;
}
public String getNews_excerpt() {
return news_excerpt;
}
public void setNews_excerpt(String news_excerpt) {
this.news_excerpt = news_excerpt;
}
public String getNews_id() {
return news_id;
}
public void setNews_id(String news_id) {
this.news_id = news_id;
}
}
Still no problems from above code.
All of NewsAdapter
public class NewsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
private ImageLoader imageLoader;
private Context mContext;
//List of newss
private List<NewsItems> mNewsItems;
private final int VIEW_ITEM = 0;
private final int VIEW_PROG = 1;
private int lastPosition = -1;
public NewsAdapter(List<NewsItems> newsItems, Context context) {
super();
//Getting all newss
this.mNewsItems = newsItems;
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.news_summ, parent, false);
return new TextViewHolder(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 TextViewHolder) {
NewsItems newsList = mNewsItems.get(position);
((TextViewHolder) holder).newsTitle.setText(newsList.getNews_title());
((TextViewHolder) holder).newsExcerpt.setText(newsList.getNews_excerpt());
((TextViewHolder) holder).newsId.setText(String.valueOf(newsList.getNewsId()));
} else {
((ProgressViewHolder) holder).progressBar.setIndeterminate(true);
((ProgressViewHolder) holder).loadButton.setText(R.string.reload);
}
}
@Override
public int getItemCount(){
//Return the number of items in the data set
return mNewsItems.size();
}
public static class TextViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView newsTitle,newsExcerpt, newsId;
public ImageButton imageButton;
public NewsItems dNewsItems;
public TextViewHolder (final View newsView) {
super(newsView);
newsTitle = (TextView) newsView.findViewById(R.id.news_title);
newsExcerpt = (TextView) newsView.findViewById(R.id.news_excerpt);
newsId = (TextView) newsView.findViewById(R.id.news_id);
newsExcerpt.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v.getId() == newsExcerpt.getId()) {
if (v.getId() == newsExcerpt.getId()) {
Intent i = NewsDetails.newIntent(getActivity(), dNewsItems.getNews_id());
startActivity(i);
}
}
}
}
public static class ProgressViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
Button loadButton;
ProgressBar progressBar;
public ProgressViewHolder(View footerView){
super(footerView);
loadButton = (Button) footerView.findViewById(R.id.reload_button);
progressBar = (ProgressBar) footerView.findViewById(R.id.progress_load);
loadButton.setOnClickListener(this);
if(NetworkCheck.isAvailableAndConnected(footerView.getContext())) {
progressBar.setVisibility(View.VISIBLE);
} else if (!NetworkCheck.isAvailableAndConnected(footerView.getContext())) {
loadButton.setVisibility(View.VISIBLE);
}
}
@Override
public void onClick(View v) {
if (v.getId() == loadButton.getId()) {
//
}
}
}
}
This is the part that's giving me problems.
Specifically lines
Intent i = NewsDetails.newIntent(getActivity(), dNewsItems.getNews_id());
startActivity(i);
When I hover I hove newIntent
it says "Cannot resolve method 'newIntent(?, java.lang.String)'".
Then I hover getActivity()
it says "Cannot resolve method 'getActivity()'".
For startActivity(i);
it's "Cannot resolve method 'startActivity(android.content.Intent)'"
So now, my question is what am I doing wrong and how should I correct it?
NewsAdapter After Implementing Rohit Arya's answer
public class NewsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
private ImageLoader imageLoader;
private Context mContext;
//List of newss
private List<NewsItems> mNewsItems;
private final int VIEW_ITEM = 0;
private final int VIEW_PROG = 1;
private int lastPosition = -1;
public NewsAdapter(List<NewsItems> newsItems, Context context) {
super();
//Getting all newss
this.mNewsItems = newsItems;
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.news_summ, parent, false);
return new TextViewHolder(v, mContext);
} 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 TextViewHolder) {
NewsItems newsList = mNewsItems.get(position);
((TextViewHolder) holder).newsTitle.setText(newsList.getNews_title());
((TextViewHolder) holder).newsExcerpt.setText(newsList.getNews_excerpt());
((TextViewHolder) holder).newsId.setText(String.valueOf(newsList.getNewsId()));
} else {
((ProgressViewHolder) holder).progressBar.setIndeterminate(true);
((ProgressViewHolder) holder).loadButton.setText(R.string.reload);
}
}
@Override
public int getItemCount(){
//Return the number of items in the data set
return mNewsItems.size();
}
public static class TextViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView newsTitle,newsExcerpt, newsId;
public ImageButton imageButton;
public NewsItems dNewsItems;
private Context context;
public TextViewHolder (final View newsView, final Context context) {
super(newsView);
newsTitle = (TextView) newsView.findViewById(R.id.news_title);
newsExcerpt = (TextView) newsView.findViewById(R.id.news_excerpt);
newsId = (TextView) newsView.findViewById(R.id.news_id);
newsExcerpt.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v.getId() == newsExcerpt.getId()) {
int newsid = 4536;
Intent myItent = new Intent(context, NewsDetails.class);
myItent.putExtra("key", newsid);
context.startActivity(myItent);
}
}
}
}
public static class ProgressViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
Button loadButton;
ProgressBar progressBar;
public ProgressViewHolder(View footerView){
super(footerView);
loadButton = (Button) footerView.findViewById(R.id.reload_button);
progressBar = (ProgressBar) footerView.findViewById(R.id.progress_load);
loadButton.setOnClickListener(this);
if(NetworkCheck.isAvailableAndConnected(footerView.getContext())) {
progressBar.setVisibility(View.VISIBLE);
} else if (!NetworkCheck.isAvailableAndConnected(footerView.getContext())) {
loadButton.setVisibility(View.VISIBLE);
}
}
@Override
public void onClick(View v) {
if (v.getId() == loadButton.getId()) {
//
}
}
}
}
Stacktrace from implementing Rohit Arya's answer
04-12 20:15:25.424 8772-8772/com.newsus.app E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.newsus.app, PID: 8772
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
at android.content.ComponentName.<init>(ComponentName.java:77)
at android.content.Intent.<init>(Intent.java:4336)
at com.newsus.app.NewsAdapter$TextViewHolder.onClick(NewsAdapter.java:181)
at android.view.View.performClick(View.java:5076)
at android.view.View$PerformClick.run(View.java:20279)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5910)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1405)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1200)
From the stacktrace, line 81, coressponds to line Intent myIntent = new Intent(context, NewsDetails.class);
of his answer.
Upvotes: 1
Views: 320
Reputation: 6791
Change TextViewHolder
's constructor to receive context
like this:
public static class TextViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView newsTitle, newsExcerpt;
public ImageButton imageButton;
public NewsItems dNewsItems;
private Context context;
public TextViewHolder (final View newsView, final Context context) {
super(newsView);
this.context = context; // EDIT 1: You are missing this
newsTitle = (TextView) newsView.findViewById(R.id.news_title);
newsExcerpt = (TextView) newsView.findViewById(R.id.news_excerpt);
newsExcerpt.setOnClickListener(this);
}
Now use this context to launch activity like this:
Intent myIntent = new Intent(context, NewsDetails.class);
myIntent.putExtra("key", value); //Optional parameters
context.startActivity(myIntent);
Upvotes: 2
Reputation: 73946
ViewHolder does not have a method getActivity()
if you need context in a viewholder you have to pass it in your constructor.
same thing with startActivity()
you need context for that too
Upvotes: 0