NullPointerExceptions when parsing Json using Gson on Android - java

I'm a bit new to posting on StackOverflow. I've done a whole bunch of searching, and I can't seem to find an answer that helps me solve my specific problem.
I am trying to parse this particular Json: https://ajax.googleapis.com/ajax/services/search/images?v=1.0&q=fuzzy%20monkey%27
I'm new to Json, and I am using Google Gson in order to parse it. It compiles fine. However it doesn't seem as if my Java classes are being populated with the proper info from the Json (I keep getting NullPointerExceptions), which is probably due to my lack of knowledge about Json. In this code, the NullPointerException comes specifically from the final int N = response.results.size() line from my Main Activity.
My Main Activity:
public class MainActivity extends ActionBarActivity {
public static InputStream json;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
ResponseData response = new ResponseData();
new JsonAsync(this, response).execute();
final int N = response.results.size();
final TextView[] myTextViews = new TextView[N]; // create an empty array;
for (int i = 0; i < N; i++) {
// create a new textview
final TextView textView = new TextView(this);
textView.setText("Image Name:" + response.results.get(i).titleNoFormatting);
RelativeLayout myLayout = (RelativeLayout) findViewById(R.id.container);
// add the textview to the linearlayout
myLayout.addView(textView);
// save a reference to the textview for later
myTextViews[i] = textView;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
return rootView;
}
}
/**
* Async Task for Grabbing Json Data
*
*/
private static class JsonAsync extends AsyncTask<Void, Void, ResponseData> {
private String text;
public InputStream stream;
private Activity activity;
private ResponseData response;
public JsonAsync(Activity activity, ResponseData response) {
this.activity = activity;
this.response = response;
}
#Override
protected ResponseData doInBackground(Void...params) {
try {
URL url = new URL("https://ajax.googleapis.com/ajax/services/search/images?v=1.0&q=fuzzy%20monkey%27");
InputStream stream = url.openStream();
Gson gson = new Gson();
String json = convertStreamToString(stream);
ResponseData response = gson.fromJson(json, ResponseData.class);
return response;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(ResponseData result) {
super.onPostExecute(result);
}
public static String convertStreamToString(java.io.InputStream is) {
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
}
}
My Result Class:
public class Result {
public int width;
public int height;
public String visibleUrl;
public String titleNoFormatting;
public URL url;
public Result () {
}
}
My ResponseData class:
public class ResponseData {
public List<Result> results;
}
I was starting off very basic, just taking a few values from the Json to put into the class and trying to display just the names of the image searches in dynamically created TextViews (based on the search count). I have network permissions already declared in the manifest so I don't think it's a network problem. Any help would be appreciated!

You should put all your code that depends on asynctask in onPostExecute.
#Override
protected void onPostExecute(ResponseData result) {
final int N = result.results.size();
final TextView[] myTextViews = new TextView[N]; // create an empty array;
for (int i = 0; i < N; i++) {
// create a new textview
final TextView textView = new TextView(MainActivity.this);
textView.setText("Image Name:" + result.results.get(i).titleNoFormatting);
RelativeLayout myLayout = (RelativeLayout) findViewById(R.id.container);
// add the textview to the linearlayout
myLayout.addView(textView);
// save a reference to the textview for later
myTextViews[i] = textView;
}
super.onPostExecute(result);
}
EDIT:
I missed a thing. Wherever was response.results use result.results instead. It was in two lines:
final int N = result.results.size();
and
textView.setText("Image Name:" + result.results.get(i).titleNoFormatting);
If you get null again, maybe it is because name of your class 'ResponseData' and mark in json 'responseData' are not the same (first letter).

Related

Recyclerview empty on first load

Hi like it says in the title im trying to make my recyclerview work but it always show empty on first load. Only when i change activity and come back it appear. The data is fetched on create but dont seem to get passed to the adapter.
So my question is : How to load data in recyclerview on first load ?
RecyclerViewFragment.java
private static final String TAG = "RecyclerViewFragment";
private static final String KEY_LAYOUT_MANAGER = "layoutManager";
private static final int SPAN_COUNT = 2;
private static final int DATASET_COUNT = 60;
public static ArrayList<String> arraylist_News = new ArrayList<String>();
public static ArrayList<String> arraylist_Thumbs = new ArrayList<String>();
public static ArrayList<String> arraylist_Links = new ArrayList<String>();
private static String URL = "https://mangascan.cc/";
public String titre;
public String name;
public String img;
public String lien;
private enum LayoutManagerType {
GRID_LAYOUT_MANAGER,
LINEAR_LAYOUT_MANAGER
}
protected LayoutManagerType mCurrentLayoutManagerType;
protected RadioButton mLinearLayoutRadioButton;
protected RadioButton mGridLayoutRadioButton;
protected RecyclerView mRecyclerView;
protected CustomAdapter mAdapter;
protected RecyclerView.LayoutManager mLayoutManager;
protected String[] mDataset;
protected String[] mDatasetName;
protected String[] mDatasetImg;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Initialize dataset, this data would usually come from a local content provider or
// remote server.
initDataset();
new getWebsite().execute();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.recycler_view_frag, container, false);
rootView.setTag(TAG);
// BEGIN_INCLUDE(initializeRecyclerView)
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
//mRecyclerView.setHasFixedSize(false);
// LinearLayoutManager is used here, this will layout the elements in a similar fashion
// to the way ListView would layout elements. The RecyclerView.LayoutManager defines how
// elements are laid out.
mLayoutManager = new LinearLayoutManager(getActivity());
mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
if (savedInstanceState != null) {
// Restore saved layout manager type.
mCurrentLayoutManagerType = (LayoutManagerType) savedInstanceState
.getSerializable(KEY_LAYOUT_MANAGER);
}
setRecyclerViewLayoutManager(mCurrentLayoutManagerType);
// END_INCLUDE(initializeRecyclerView)
// getParentFragmentManager().beginTransaction().detach(this).attach(this).commit();
mAdapter = new CustomAdapter(getActivity(),mDataset,mDatasetName,mDatasetImg);
// Set CustomAdapter as the adapter for RecyclerView.
mRecyclerView.setAdapter(mAdapter);
mAdapter.ResetValues(mDataset);
// mAdapter.notifyItemRangeChanged(0, arraylist_News.size());
return rootView;
}
/**
* Set RecyclerView's LayoutManager to the one given.
*
* #param layoutManagerType Type of layout manager to switch to.
*/
public void setRecyclerViewLayoutManager(LayoutManagerType layoutManagerType) {
int scrollPosition = 0;
// If a layout manager has already been set, get current scroll position.
if (mRecyclerView.getLayoutManager() != null) {
scrollPosition = ((LinearLayoutManager) mRecyclerView.getLayoutManager())
.findFirstCompletelyVisibleItemPosition();
}
mLayoutManager = new LinearLayoutManager(getActivity(),RecyclerView.HORIZONTAL, false);
mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.scrollToPosition(scrollPosition);
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save currently selected layout manager.
savedInstanceState.putSerializable(KEY_LAYOUT_MANAGER, mCurrentLayoutManagerType);
super.onSaveInstanceState(savedInstanceState);
}
/**
* Generates Strings for RecyclerView's adapter. This data would usually come
* from a local content provider or remote server.
*/
private void initDataset() {
mDataset = new String[arraylist_News.size()];
for (int i = 0; i < arraylist_News.size(); i++) {
mDataset[i] = String.valueOf(arraylist_News.get(i));
}
mDatasetName = new String[arraylist_Links.size()];
for (int i = 0; i < arraylist_Links.size(); i++) {
mDatasetName[i] = String.valueOf(arraylist_Links.get(i));
}
mDatasetImg = new String[arraylist_Thumbs.size()];
for (int i = 0; i < arraylist_Thumbs.size(); i++) {
mDatasetImg[i] = String.valueOf(arraylist_Thumbs.get(i));
}
}
private class getWebsite extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
arraylist_News.clear();
arraylist_Thumbs.clear();
arraylist_Links.clear();
}
private static final String userAgent = "Mozilla/5.0 (jsoup)";
#Override
protected Void doInBackground(Void... voids) {
try {
Document doc = Jsoup.connect(URL).userAgent(userAgent).timeout(12000).get();
//scan-mangas get news script
Element news = doc.select(".hot-thumbnails").first();
// Log.d("jSoup", news.toString());
for (Element e : news.select(".span3")){
titre = e.select("p").text().toString();
//Log.d("okk", titre);
img = e.select("img").attr("src");
lien = e.select("a").attr("href");
name = e.getElementsByClass("label label-warning").text().toString();
arraylist_News.add((titre));
arraylist_Thumbs.add(img);
arraylist_Links.add(name);
}
for (String str_Agil : arraylist_Thumbs) // using foreach
{
Log.e("NEWS:: " , str_Agil);
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
// This code will always run on the UI thread, therefore is safe to modify UI elements.
((CustomAdapter)mRecyclerView.getAdapter()).ResetValues(mDataset);
mAdapter.notifyDataSetChanged();
mAdapter.notifyItemRangeInserted(0, arraylist_News.size());
//System.out.println("update ui");
mRecyclerView.removeAllViews();
}
});
}
}
CustomAdapter.java
private String[] mDataSet;
private String[] mDataSetName;
private String[] mDataSetImg;
Context context;
// BEGIN_INCLUDE(recyclerViewSampleViewHolder)
/**
* Provide a reference to the type of views that you are using (custom ViewHolder)
*/
public static class ViewHolder extends RecyclerView.ViewHolder {
private final TextView textView;
private final TextView textView2;
private final ImageView imgView;
public ViewHolder(View v) {
super(v);
// Define click listener for the ViewHolder's View.
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "Element " + getAdapterPosition() + " clicked.");
}
});
textView = (TextView) v.findViewById(R.id.textView);
textView2 = (TextView) v.findViewById(R.id.textView2);
imgView = (ImageView) v.findViewById(R.id.thumbnail);
}
public TextView getTextView() {
return textView;
}
public TextView getTextView2() {
return textView2;
}
}
// END_INCLUDE(recyclerViewSampleViewHolder)
/**
* Initialize the dataset of the Adapter.
*
* #param dataSet String[] containing the data to populate views to be used by RecyclerView.
*/
public CustomAdapter(Context context, String[] dataSet, String[] dataSet1, String[] dataSet2) {
mDataSet = dataSet;
mDataSetName = dataSet1;
mDataSetImg = dataSet2;
this.context = context;
}
// BEGIN_INCLUDE(recyclerViewOnCreateViewHolder)
// Create new views (invoked by the layout manager)
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
// Create a new view.
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.text_row_item, viewGroup, false);
return new ViewHolder(v);
}
// END_INCLUDE(recyclerViewOnCreateViewHolder)
// BEGIN_INCLUDE(recyclerViewOnBindViewHolder)
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
Log.d(TAG, mDataSet[position] + " set.");
// Get element from your dataset at this position and replace the contents of the view
// with that element
viewHolder.getTextView().setText(mDataSet[position]);
viewHolder.getTextView2().setText(mDataSetName[position]);
Picasso.with(viewHolder.imgView.getContext()).load(mDataSetImg[position]).into(viewHolder.imgView);
}
// END_INCLUDE(recyclerViewOnBindViewHolder)
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataSet.length;
}
public void ResetValues(String[] dataSet)
{
notifyDataSetChanged();
}
Thanks fellows devs
Bump
heres the full project so you can test it : https://drive.google.com/file/d/15rx7vELGiwlIfxZH3Np6Joycrsf4PxO_/view?usp=sharing
i been struggling for three months on this please help
This solution based on code in Google drive
Goto PageViewFragment.java and change this
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
// This code will always run on the UI thread, therefore is safe to modify UI elements.
if(pageAdapter==null){
pageAdapter =new PageAdapter(getActivity(), mDataset);
mRecyclerView.setAdapter(pageAdapter);
} else {
pageAdapter.notifyDataSetChanged();
Log.d("dataset", "changed");
}
}
});
To this
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
// This code will always run on the UI thread, therefore is safe to modify UI elements.
initDataset();
pageAdapter = new PageAdapter(getActivity(), mDataset);
mRecyclerView.setAdapter(pageAdapter);
}
});

Integrating Loaders and recycler view not working

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();
}

Custom Adapter on applying on list view

I have made a custom Adapter and populate it with the data. I have used Logcat to see whether the array i'm passing to custom Adapter class contains the data and it does.
The error i got is following. It occurs when this CategoryBlog is created. Activity is created but it does not contain list view
exception: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference
'mainblogpost' contains the array with all the data i want to populate with.
'MainListActivityAdapter' is the Adapter Class.
'Category_Blogs' is the class where i want to set the list view.
Category_Blog.java
I don't add import statement. there is no error in it
public class Category_Blogs extends AppCompatActivity implements AbsListView.OnItemClickListener {
public static final String TAG = MainActivity.class.getSimpleName();
public final static String EXTRA_MESSAGE = "com.example.talha.appforblog.MESSAGE";
List<StackOverflowXmlParser.Entry> mainBlogPost = new ArrayList<StackOverflowXmlParser.Entry>();
private ListAdapter mAdapter;
private AbsListView mListView;
private ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_category__blogs);
//Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar);
//setSupportActionBar(toolbar);
Intent intent = getIntent();
String message = intent.getStringExtra(Tab2.EXTRA_MESSAGE);
String link = message.trim() + "?feed=titles";
Log.d("ye category click krne par next activity me ye link bnta hy parsing ke liye",link);
loadPage(link);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_category__blogs, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void loadPage(String link) {
Log.d(TAG, "loadpage me a gae nh");
// if((sPref.equals(ANY)) && (wifiConnected || mobileConnected)) {
new DownloadXmlTask(this).execute(link);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
private class DownloadXmlTask extends AsyncTask<String, Void, List<StackOverflowXmlParser.Entry>> {
private Context mContext;
public DownloadXmlTask(Context context) {
mContext = context;
}
#Override
protected List<StackOverflowXmlParser.Entry> doInBackground(String... urls) {
try {
return loadXmlFromNetwork(urls[0]);
} catch (Exception e) {
Log.d("test", "" + e);
}
return null;
}
#Override
protected void onPostExecute(List<StackOverflowXmlParser.Entry> results) {
if (results != null) {
try {
String title, link, image, pubDate;
Log.d("test", "onpost");
// custom array adapter
ArrayList<HashMap<String, String>> blogPosts = new ArrayList<HashMap<String, String>>();
for (StackOverflowXmlParser.Entry result : results) {
title = result.title;
link = result.link;
image = result.image;
pubDate = result.pubDate;
HashMap<String, String> blogPost = new HashMap<String, String>();
blogPost.put("link", link);
blogPost.put("title", title);
blogPost.put("image", image);
blogPost.put("pubDate", pubDate);
blogPosts.add(blogPost);
}
// copying to main item List array
for (int i = 0; i < results.size(); i++) {
mainBlogPost.add(results.get(i));
}
Log.d("fff", results.get(1).pubDate);
MainListActivityAdapter mAdapter =
new MainListActivityAdapter(Category_Blogs.this, mainBlogPost);
listView.setAdapter(mAdapter);
//((AdapterView<ListAdapter>) mListView).setAdapter(mAdapter);
// Set OnItemClickListener so we can be notified on item clicks
mListView.setOnItemClickListener(Category_Blogs.this);
}
catch (Exception e){
Log.d("test", "exception: "+e);
}
}
}
private List<StackOverflowXmlParser.Entry> loadXmlFromNetwork(String urlString) throws XmlPullParserException, IOException {
InputStream stream = null;
// Instantiate the parser
StackOverflowXmlParser stackOverflowXmlParser = new StackOverflowXmlParser();
List<StackOverflowXmlParser.Entry> entries = null;
String title = null;
String url = null;
try {
//opening the connection and fetching
stream = downloadUrl(urlString);
entries = stackOverflowXmlParser.parse(stream);
// Makes sure that the InputStream is closed after the app is
// finished using it.
} catch (Exception e) {
Log.d("test", "" + e);
} finally {
if (stream != null) {
stream.close();
}
}
for (StackOverflowXmlParser.Entry entry : entries) {
Log.d("aaa",entry.pubDate);
}
return entries;
}
private InputStream downloadUrl(String urlString) throws IOException {
java.net.URL url = new java.net.URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// Starts the query
conn.connect();
return conn.getInputStream();
}
}
}
MainListActivityAdapter.java
public class MainListActivityAdapter extends BaseAdapter {
private Activity activity;
List<StackOverflowXmlParser.Entry> mainBlogPost = new ArrayList<StackOverflowXmlParser.Entry>();
private static LayoutInflater inflater = null;
public MainListActivityAdapter(Activity a, List<StackOverflowXmlParser.Entry> main) {
activity = a;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mainBlogPost = main;
}
public int getCount() {
return mainBlogPost.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
Log.d("test", "fetching" + position);
String tit = mainBlogPost.get(position).title;
String cate = mainBlogPost.get(position).pubDate;
String pub = mainBlogPost.get(position).pubDate;
String image_url = "http://download.androidhive.info/img/btn_fb_login.png";
if (convertView == null)
vi = inflater.inflate(R.layout.list_row, null);
TextView title = (TextView) vi.findViewById(R.id.title); // title
TextView cat = (TextView) vi.findViewById(R.id.category); // category
ImageView image = (ImageView) vi.findViewById(R.id.list_image); // image
TextView publish = (TextView) vi.findViewById(R.id.pubDate); // publish date
// Setting all values in listview
title.setText(tit);
cat.setText(cate);
publish.setText(pub);
Glide.with(activity)
.load(image_url)
.into(image);
return vi;
}
}
Activity_category_blog.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent"
android:layout_height="wrap_content" tools:context="com.example.talha.test_fragement.Category_Blogs"
xmlns:ads="http://schemas.android.com/apk/res-auto">
<include layout="#layout/tool_bar" />
<FrameLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#layout/tool_bar">
<ListView android:id="#android:id/list" android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/adView" android:divider="#b5b5b5"
android:dividerHeight="1dp"
android:layout_alignParentBottom="true"
/>
<TextView android:id="#android:id/empty" android:layout_width="match_parent"
android:layout_height="match_parent" android:gravity="center"
android:layout_gravity="right|top" />
</FrameLayout>
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_category__blogs);
listView = (ListView) findViewById(R.id.lvID);//where lvID is id from your listview placed in activity_category__blogs layout.
You fail to initialize the listview.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_category__blogs);
//Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar);
**listView = (ListView) findViewById(R.id.list);**
//setSupportActionBar(toolbar);
Intent intent = getIntent();
String message = intent.getStringExtra(Tab2.EXTRA_MESSAGE);
String link = message.trim() + "?feed=titles";
Log.d("ye category click krne par next activity me ye link bnta hy parsing ke liye",link);
loadPage(link);
}

Parsing JSON Data in a RecylcerView within a fragment

I need some help with the logic to my problem. I have searched already on here for posts discussing similar issues, however haven't yet had success in fixing my problem so I don't wish to make this a duplicate post.
I am working on an app and I am having issues in displaying parsed JSON Data in a recycler view within a Slide Tab Fragment. I have a Sliding Tabs on my main activity with five fragments in total, one for each tab (5 tabs in total). What I want to do for the third tab is to display a recycler view with parsed JSON data that is being retrieved from the server. I have the same functionality within an activity for my other recyclerviews and they work fine. I was just struggling slightly on how to achieve this inside a fragment. I am providing the below code for troubleshooting and debugging purposes:
Here is the code to my MainActivity.java
public class MainActivity extends BaseActivity {
private ViewPager mPager;
private SlidingTabLayout mTabs;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// To track statistics around application
ParseAnalytics.trackAppOpened(getIntent());
// inform the Parse Cloud that it is ready for notifications
ParseInstallation.getCurrentInstallation().saveInBackground();
//Calling Activate Toolbar method
activateToolBar();
mPager = (ViewPager) findViewById(R.id.pager);
//Setting the Adapter on the view pager first. Passing the fragment manager through as an argument
mPager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
mTabs = (SlidingTabLayout) findViewById(R.id.tabs);
//Setting the custom Tab View as the Sliding Tabs Layout
mTabs.setCustomTabView(R.layout.custom_tab_view, R.id.tabText);
mTabs.setDistributeEvenly(true);
//mTabs.setSelectedIndicatorColors(getResources().getColor(R.color.tabIndicatorColour));
mTabs.setBackgroundColor(getResources().getColor(R.color.basePrimaryBackgroundColour));
//Setting the ViewPager as the tabs
mTabs.setViewPager(mPager);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
//getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
//int id = item.getItemId();
//noinspection SimplifiableIfStatement
//if (id == R.id.action_settings) {
// return true;
//}
return super.onOptionsItemSelected(item);
}
class MyPagerAdapter extends FragmentPagerAdapter {
String[] tabs;
public MyPagerAdapter(FragmentManager fm) {
super(fm);
//Initialising the strings array of the tabs
tabs = getResources().getStringArray(R.array.tabs);
}
/*
//Setting up integer array of icons
int icons[] = {R.drawable.about_us, R.drawable.campus, R.drawable.events, R.drawable.learning, R.drawable.sewa};
//Defined from strings.xml
String[] tabText = getResources().getStringArray(R.array.tabs);
public MyPagerAdapter(FragmentManager fm) {
super(fm);
//Initialising the strings array of tabs
tabText = getResources().getStringArray(R.array.tabs);
}
*/
#Override
public Fragment getItem(int position) {
if (position == 0) // if the position is 0 we are returning the First tab
{
Tab1 tab1 = new Tab1();
return tab1;
} else if (position == 1)
{
Tab2 tab2 = new Tab2();
return tab2;
} else if (position == 2)
{
Tab3 tab3 = new Tab3();
return tab3;
} else if (position == 3)
{
Tab4 tab4 = new Tab4();
return tab4;
} else
{
Tab5 tab5 = new Tab5();
return tab5;
}
}
#Override
public CharSequence getPageTitle(int position) {
//Return the text of the position clicked and display this as the title for the tab
return tabs[position];
}
#Override
public int getCount() {
return 5;
}
}
}
This is the code for my RecyclerViewAdapterEvents.java
public class RecyclerViewAdapterEvents extends RecyclerView.Adapter<RecyclerViewAdapterEvents.MyViewHolder> {
private LayoutInflater inflater;
//private EventsActivity activity;
private List<JSONEventsItem> data = Collections.emptyList();
private Context mContext;
//Variable for the on click Listener
private ClickListener clickListener;
//Passing in the array list argument
public RecyclerViewAdapterEvents(Context context, List<JSONEventsItem> data) {
this.mContext = context;
//this.activity = activity;
inflater = LayoutInflater.from(context);
//Setting the array list data to the argument passed in
this.data = data;
}
#Override
public RecyclerViewAdapterEvents.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//Inflating the row and getting the root of view of the custom row (Linear Layout)
View view = inflater.inflate(R.layout.custom_row, parent, false);
//Passing the root view through as an argument
MyViewHolder holder = new MyViewHolder(view);
//Returning the view holder
return holder;
}
#Override
public void onBindViewHolder(RecyclerViewAdapterEvents.MyViewHolder holder, int position) {
//This will get the current position of the JSONEventItem object from the array
JSONEventsItem eventsItem = data.get(position);
//Setting the event name to the name of the event retrieved from the Database (converting from JSON)
holder.eventName.setText(Html.fromHtml(eventsItem.getEventName()));
}
#Override
public int getItemCount() {
return (null != data ? data.size() : 0);
}
public void setClickListener(ClickListener clicklistener) {
this.clickListener = clicklistener;
}
public interface ClickListener {
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView eventName;
public MyViewHolder(View itemView) {
super(itemView);
//Here setting the id of the textview in the recycler view holder to be the list view from the custom_row xml
eventName = (TextView) itemView.
findViewById(R.id.listText);
}
}
}
Here is the class file for Tab3 Fragment, Tab3.java
public class Tab3 extends Fragment implements RecyclerViewAdapterEvents.ClickListener{
private RecyclerView mRecyclerView;
//Creating an instance of the adapter object
private RecyclerViewAdapterEvents adapter;
private List<JSONEventsItem> EventsList;
private String jsonString = "";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View v = inflater.inflate(R.layout.tab_3,container,false);
//Instantiating the recycler view as defined in tab_1
mRecyclerView = (RecyclerView) v.findViewById(R.id.about_us_recycler_view);
//Adding item decoration. Recycler view divider
mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
//Initialising the adapter - Passing in the activity and the getData method
adapter = new RecyclerViewAdapterEvents(getActivity(), EventsList);
//Here passing in the click listener into the Adapter. 'this' signifies that it is the fragment that handles the click listener.
//This is possible as the on Click Listener interface is being implemented.
adapter.setClickListener(this);
//Setting the adapter
mRecyclerView.setAdapter(adapter);
//Setting the Layout
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//Downloading data from below url (Universal Resource Locator) to obtain data from the Admin database
final String url = "http://dbchudasama.webfactional.com/jsonscript.php";
new AsyncHTTPTask().execute(url);
return v;
}
public class AsyncHTTPTask extends AsyncTask<String, Void, Integer> {
#Override
protected Integer doInBackground(String... params) {
Integer result = 0;
HttpURLConnection urlConnection;
try {
URL url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
int statusCode = urlConnection.getResponseCode();
// 200 represents HTTP OK
if (statusCode == 200) {
BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
response.append(line);
}
jsonString = response.toString();
parseResult();
result = 1; // Successful
} else {
result = 0; //"Failed to fetch data!";
}
} catch (Exception e) {
Log.d("Exception Caught", e.getLocalizedMessage());
}
return result; //"Failed to fetch data!";
}
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
//adapter.getItemCount();
if (result == 1) {
//Intent intent = getIntent();
//intent.getSerializableExtra("JSON Admin");
//Initialising the adapter - Passing in the activity and the parsed Admin Team List
adapter = new RecyclerViewAdapterEvents(getActivity(), EventsList);
//Setting the adapter
mRecyclerView.setAdapter(adapter);
} else {
Toast.makeText(getActivity(), "Failed to fetch data!", Toast.LENGTH_SHORT).show();
}
}
}
//This method will parse the RAW data downloaded from the server
private void parseResult() {
try {
JSONArray AdminArrays = new JSONArray(jsonString);
EventsList = new ArrayList<>();
for (int i = 0; i < AdminArrays.length(); i++) {
JSONObject AdminArrayObject = AdminArrays.getJSONObject(i);
JSONEventsItem item = new JSONEventsItem();
item.setEventName(AdminArrayObject.getString("eventName"));
this.EventsList.add(item);
Log.e("Event Name", AdminArrayObject.getString("eventName"));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
The Tab3.java code has crashed all my other tabs and is giving a null pointer exception on the the getActivity() method, as this is being performed on a null object reference. Could I just declare an activity of type EventsActivity and pass this through instead? Also So I am slightly unsure how to resolve this. For completeness I have also written the same code within an activity EventsActivity.java which I know will work. It is just getting it to run within the fragment.
public class EventsActivity extends BaseActivity implements RecyclerViewAdapterEvents.ClickListener {
private RecyclerView mRecyclerView;
//Creating an instance of the adapter object
private RecyclerViewAdapterEvents adapter;
private List<JSONEventsItem> EventsList;
private EventsActivity activity;
private String jsonString = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tab_3);
//Calling Activate Toolbar method (with the Back button enabled)
activateToolbarWithHomeEnabled();
//Instantiating the recycler view as defined in admin_team
//mRecyclerView = (RecyclerView) findViewById(R.id.events_recycler_view);
//Adding item decoration. Recycler view divider
mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));
//Initialising the adapter - Passing in the activity and the parsed Events List
adapter = new RecyclerViewAdapterEvents(this, EventsList);
//Setting the adapter
mRecyclerView.setAdapter(adapter);
//Setting the Layout
//mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//Downloading data from below url (Universal Resource Locator) to obtain data from the Admin database
final String url = "http://dbchudasama.webfactional.com/jsonscript.php";
new AsyncHTTPTask().execute(url);
}
public class AsyncHTTPTask extends AsyncTask<String, Void, Integer> {
#Override
protected Integer doInBackground(String... params) {
Integer result = 0;
HttpURLConnection urlConnection;
try {
URL url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
int statusCode = urlConnection.getResponseCode();
// 200 represents HTTP OK
if (statusCode == 200) {
BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
response.append(line);
}
jsonString = response.toString();
parseResult();
result = 1; // Successful
} else {
result = 0; //"Failed to fetch data!";
}
} catch (Exception e) {
Log.d("Exception Caught", e.getLocalizedMessage());
}
return result; //"Failed to fetch data!";
}
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
//adapter.getItemCount();
if (result == 1) {
//Intent intent = getIntent();
//intent.getSerializableExtra("JSON Admin");
//Initialising the adapter - Passing in the activity and the parsed Admin Team List
adapter = new RecyclerViewAdapterEvents(EventsActivity.this, EventsList);
//Setting the adapter
mRecyclerView.setAdapter(adapter);
} else {
Toast.makeText(EventsActivity.this, "Failed to fetch data!", Toast.LENGTH_SHORT).show();
}
}
}
//This method will parse the RAW data downloaded from the server
private void parseResult() {
try {
JSONArray AdminArrays = new JSONArray(jsonString);
EventsList = new ArrayList<>();
for (int i = 0; i < AdminArrays.length(); i++) {
JSONObject AdminArrayObject = AdminArrays.getJSONObject(i);
JSONEventsItem item = new JSONEventsItem();
item.setEventName(AdminArrayObject.getString("eventName"));
this.EventsList.add(item);
Log.e("Event Name", AdminArrayObject.getString("eventName"));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
Here is my crash log from Logcat:
11-09 18:56:21.587 2961-2961/com.divyeshbc.NHSF E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.divyeshbc.NHSF, PID: 2961
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.addItemDecoration(android.support.v7.widget.RecyclerView$ItemDecoration)' on a null object reference
at com.divyeshbc.NHSF.tabs.events.Tab3.onCreateView(Tab3.java:53)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1789)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:955)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1138)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:740)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1501)
at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:490)
at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1105)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:551)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:513)
at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:494)
at com.divyeshbc.NHSF.tabs.SlidingTabLayout$TabClickListener.onClick(SlidingTabLayout.java:324)
at android.view.View.performClick(View.java:4756)
at android.view.View$PerformClick.run(View.java:19749)
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:5221)
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:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Where am I going wrong? Any guidance will be highly helpful :).
Thanks

AsyncTask onPostExecute TextView not updating

My situation is like this:
My main activity has 3 fragments. The first fragment requests data from the server and tries to render it. I use an AsyncTask inner class to get the data and render in onPostExecute. I render using a SimpleCursorAdapter with a ListView. Rendering works fine. After this is done, I try to manipulate the UI (set value of a TextView) but it is not working. getViewById does not return null or any errors but I still cannot change the value for some reason. Any suggestions are highly appreciated. Here is the Fragment Class that I use:
public class FeedFragment extends Fragment {
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_feed, container, false);
Activity activity = getActivity();
try {
new getFeedData(activity,rootView).execute();
}
finally{
return rootView;
}
}
private class getFeedData extends AsyncTask<Void, Void, String> {
private Context activity;
private View rootView;
public getFeedData(Context context, View main){
this.activity=context;
this.rootView=main;
}
#Override
protected String doInBackground(Void... params) {
try {
HttpRequest request = HttpRequest.get("http://upinion.us/test/feed_sample/");
String response = "";
if (request.ok()) {
response = request.body();
}
return response;
} catch (HttpRequestException exception) {
return null;
}
}
#Override
protected void onPostExecute(String response) {
String[] columns = new String[] {"_id","title","description"};
int[] viewIds = new int[] {R.id.postId,R.id.title,R.id.description};
JSONArray finalResponse;
try {
finalResponse = new JSONArray(response);
} catch (JSONException e) {
e.printStackTrace();
finalResponse = null;
}
MatrixCursor mc = new MatrixCursor(new String[] {"_id","title","description"}); // properties from the JSONObjects
for (int i = 0; i < finalResponse.length(); i++) {
JSONObject jsonObject;
try {
jsonObject = finalResponse.getJSONObject(i);
mc.addRow(new Object[] {jsonObject.get("_id"),jsonObject.get("title"),jsonObject.get("description")});
} catch (JSONException e) {
jsonObject=null;
}
}
SimpleCursorAdapter mAdapter = new SimpleCursorAdapter(getActivity(), R.layout.post, mc, columns, viewIds,0);
ListView list = (ListView) this.rootView.findViewById(R.id.feed_feed);
list.setAdapter(mAdapter);
View v;
for (int i = 0; i < list.getCount(); i++) {
v = list.getAdapter().getView(i, null, null);
TextView text = (TextView) v.findViewById(R.id.title);
text.setText("HELLO MOTO");
}
list.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// selected item
Integer convId = parent.getId();
}
});
}
}
}
As you can see, I pass the activity and the inflated root view to the asynctask, but still no luck. I have spent nearly two days trying to find a solution with no success.
for (int i = 0; i < list.getCount(); i++) {
v = list.getAdapter().getView(i, null, null);
TextView text = (TextView) v.findViewById(R.id.title);
text.setText("HELLO MOTO");
}
this is your problem:
you are NOT supposed to call getView yourself
to update your listview, you need to call adapter.notifyDataSetChanged
and the system will call the updates for you
so remove this piece of code entirely and just replace it with adapter.notifyDataSetChanged

Categories

Resources