-1

My strings (this are the strings : headings[], descs[], url[], urlToImg[]) are getting initialized after I use them which is causing nullPointerException! How to implement string initialization so that my strings can be dynamically initialized?

Here I'm initializing strings run-time with help of parseResult() method, which is called by a class which extends AsyncTask class. pasrseResult() method is initializing strings! But in the mean time strings are getting used by main thread in onCreate() method while creating object of "NewsAdapter", so strings are null causing nullPointerException!

package com.example.pritam.medoc;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Objects;

public class FragmentNews extends Fragment {


    String newsAPIUrl;

    ListView newsList;
    String headings[];
    String descs[];
    String url[];
    String urlToImg[];
    //strore url for images in string[]

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {


        newsAPIUrl ="Some APIKey that i have";
        new AsyncHTTPTask().execute(newsAPIUrl);


        View v=inflater.inflate(R.layout.fragment_news,container,false);
        newsList=v.findViewById(R.id.listview_news);


        NewsAdapter newsAdapter=new NewsAdapter(Objects.requireNonNull(getActivity()).getApplicationContext(),headings,descs,url,urlToImg);
        newsList.setAdapter(newsAdapter);

        /*newsList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                //this how to acces link from adapter table String a[]=newsAdapter.adp_descs;
                //redirect to the news!

            }
        });*/


        return inflater.inflate(R.layout.fragment_news,container,false);
    }

    class NewsAdapter extends ArrayAdapter<String>
    {
        Context context;
        String adp_headings[];
        String adp_descs[];
        String adp_url[];
        String adp_urlToImg[];
        //try to store url for images
        NewsAdapter(Context c, String _head[], String _desc[],String _url[], String _urlToImg[])
        {
            super(c,R.layout.adapter_listview,R.id.news_heading,_head);
            this.context=c;
            this.adp_headings=_head;
            this.adp_descs=_desc;
            this.adp_url=_url;
            this.adp_urlToImg=_urlToImg;
        }

        @NonNull
        @Override
        public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
            LayoutInflater layoutInflater=(LayoutInflater)getActivity().getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View customListLayout=layoutInflater.inflate(R.layout.adapter_listview,parent,false);

            ImageView news_img=customListLayout.findViewById(R.id.news_image);
            TextView news_head=customListLayout.findViewById(R.id.news_heading);
            TextView news_desc=customListLayout.findViewById(R.id.news_desc);

            //here try to populate image from url news_img.setImageResource();
            news_head.setText(adp_headings[position]);
            news_desc.setText(adp_descs[position]);

            return customListLayout;
        }
    }

    public class AsyncHTTPTask extends AsyncTask<String, Void, String>
    {

        @Override
        protected String doInBackground(String... urls) {
            String result="";
            URL this_url;
            HttpURLConnection urlConnection;
            try{
                this_url=new URL(urls[0]);
                urlConnection=(HttpURLConnection)this_url.openConnection();
                String response=streamToString(urlConnection.getInputStream());
                parseResult(response);
                return response;
            }
            catch (Exception e)
            {
             Log.i("",e.toString());
            }
            return null;
        }
    }

    String streamToString(InputStream stream)throws IOException
    {
        BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(stream));
        String data;
        String result="";

        while ((data=bufferedReader.readLine()) != null)
        {
            result+=data;
        }
        if(null != stream)
        {
            stream.close();
        }
        return result;
    }

    private void parseResult(String result) throws JSONException {
        JSONObject response=new JSONObject(result);
        JSONArray articles=response.optJSONArray("articles");

        headings=new String[articles.length()];
        descs=new String[articles.length()];
        url=new String[articles.length()];
        urlToImg=new String[articles.length()];

        for(int i=0; i<articles.length(); i++)
        {
            JSONObject article=articles.optJSONObject(i);
            headings[i]=article.optString("title");
            //Log.i("Title",headings[i]);

            descs[i]=article.optString("description");
            //Log.i("Description",descs[i]);

            url[i]=article.optString("url");
            //Log.i("url",url[i]);

            urlToImg[i]=article.optString("urlToImage");
            //Log.i("urlToImage",urlToImg[i]);
        }
    }
}

Here while creating object of NewsAdapter, I'm getting that error!

pritam parab
  • 85
  • 2
  • 10
  • @uneq95 If i do that, It'll run properly, but with empty strings! I was asking why my string are not getting populated? – pritam parab Jul 27 '19 at 15:13

1 Answers1

0

Your strings are not getting populated because the AsyncTask for fetching data and the code for populating the list run in parallel. By the time your async task completes its execution the list is already populated. You need to understand that the task coded in the async task happens in a separate thread.

What you wanna do is to populate the list after your async task gets data from the API. You must check how to update your list from the async task (You might want to search for method runOnUiThread. I might be wrong with this method as it has been a long time since I worked on Android. But I am sure my approach is correct).

You can also check the following links.

How to update ui from asynctask

Android basics: running code in the UI thread

uneq95
  • 2,158
  • 2
  • 17
  • 28