2

I am looking for a way to parse a JSON-String from an URL and then pass it to GSON to deserialize it. My goal is to put the conversed text into an RecyclerViewAdapter.

I have already tried to implement the suggestions and recommendations Parsing JSON from URL but the approach does not work for me.

First I created a JavaObject-class (called Data) with 4 attributes. These attributes are identical to the fields in my URL:

public class Data {

    private String title;
    private String version;
    private String kind;
    private String etag;

    public String getTitle() {
        return title; 
    }
    public String getVersion() {
        return version; 
    }
    public String getKind() {
        return kind; 
    }
    public String getEtag() {
        return etag; 
    }

    public void setTitle(String title) {
        this.title = title;
    }
    public void setVersion(String version) {
        this.version = version; 
    }
    public void setKind(String kind) {
        this.kind = kind; 
    }
    public void setEtag(String etag) {
        this.etag = etag; 
    }


    public String toString() {
        return String.format("title: %s, "
                        + "version: %s, "
                        + "kind: %s, "
                        + "etag: %s",
                title, version, kind, etag);
    }
}

The process of fetching the data from my URL and the conversion via GSON is supposed to take place in the following onCreateView-method of my Fragment:

 public class Fragment extends android.support.v4.app.Fragment {
   public static final String FRAGMENT_TAG = "Fragment";
   private OnListFragmentInteractionListener mListener; 

   public Fragment() {

  }

  @Override
  public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    Log.i(FRAGMENT_TAG, "onCreate()");
    setHasOptionsMenu(true);
 }


public View onCreateView(LayoutInflater inflater, ViewGroup container,       
                         Bundle savedInstanceState) {
    Log.i(JSONS_FRAGMENT_TAG, "onCreateView()");
    View view = inflater.inflate(R.layout.fragment_jsons_list, container, 
   false);
    if (view instanceof RecyclerView) {
        Context context = view.getContext();
        RecyclerView recyclerView = (RecyclerView) view;

        URL url = null;
        try {
            // Definition of the URL with the JSON-Strings
            url = new URL("http://www.jsoneditoronline.org
            /?id=b1b4f5e2526ab04b562723bccae30a40");
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        InputStreamReader reader = null;
        try {
            // InputStreamReader is responsible to open and consume the  
            // URL
            reader = new InputStreamReader(url.openStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
      // Conversion via GSON
      Data data = new Gson().fromJson(reader, Data.class);

        List<Data> listdata = new ArrayList<Data>();
        listdata.add(data);
         recyclerView.setAdapter(new     
         JSONSRecyclerViewAdapter(listdata,mListener));
    }
    return view;
}

Every time I try to run the app it stops immediately and the logcat output is indicating that there is a problem with my onCreateView-method. The logcat output is the following:

    05-08 09:21:47.179 recandroidapp E/UncaughtException:        
        android.os.NetworkOnMainThreadException                                                                                                           
        at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303)
        at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:86)
        at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:74)
        at java.net.InetAddress.getAllByName(InetAddress.java:752)
        at com.android.okhttp.internal.Network$1.resolveInetAddresses(Network.java:29)
        at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:187)
        at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:156)
        at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:98)
        at com.android.okhttp.internal.http.HttpEngine.createNextConnection(HttpEngine.java:345)
        at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:328)
        at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:246)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:457)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:405)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:243)
        at java.net.URL.openStream(URL.java:1057)
        at recandroidapp.fragments.JSONSFragment.onCreateView(JSONSFragment.java:68)
        at android.support.v4.app.Fragment.performCreateView(Fragment.java:2080)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1108)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1290)
        at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:801)
        at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1677)
        at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:536)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6077)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

In order to avoid the NetworkOnMainThreadException, I have attempted to call on AsyncTask (as suggested after my initial post by users play_err_, user12345 and Aashish Aadarsh - thanks for your help!). Unfortunately this triggers yet another error regarding the doInBackground()-method. This is the new logcat-output I receive after implementing AsyncTask: enter image description here

Do you have any ideas/suggestions? Thank you!

Community
  • 1
  • 1

4 Answers4

3

From your code, it seems that you are doing NW call on main thread and this will result in NetworkOnMainThreadException.

Try to make your NW call on AsyncTask and in postExceuteMethod you work with data (sending data to your adapter).

Aashish Aadarsh
  • 491
  • 5
  • 7
1

this is the right way

public class HomeActivity extends AppCompatActivity {

Toolbar toolbar;
RecyclerView recyclerView;
HomeActivityAdapter homeActivityAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home);

// OnCreate Method must be like this see above then your code must below
   homeActivityAdapter=new HomeActivityAdapter(list,this);//this is the recycler view adapter
    recyclerView=(RecyclerView)findViewById(R.id.recyclerview);//this is recycyler view
     recyclerView.setLayoutManager(new GridLayoutManager(this,2));
    recyclerView.setAdapter(homeActivityAdapter);


    }

it will be help full to identify the problem if you sent your stack trace. just see the Android Monitor Option below open it and sent all red color line in it image .

Rizwan
  • 163
  • 2
  • 8
1

NetworkOnMainThread exception is mainly thrown whenever an application attempts to make a networking operation on its main thread. To avoid this Use a thread or an AsyncTask.

Thread thread = new Thread(new Runnable() {

    @Override
    public void run() {
        try  {

    URL url = null;
            try {
                // Definition of the URL with the JSON-Strings
                url = new URL("http://www.jsoneditoronline.org
                /?id=b1b4f5e2526ab04b562723bccae30a40");
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
            InputStreamReader reader = null;
            try {
                // InputStreamReader is responsible to open and consume the  
                // URL
                reader = new InputStreamReader(url.openStream());
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
});

thread.start();
Pro Mode
  • 1,453
  • 17
  • 30
  • 1
    Thanks play_err_ I tried to use your approach. Unfortunately I got a NPE related to my reader-object when the thread.start()-method was called. After the call I am trying to set the reader-instance as a parameter to GSON-class, see: 'Data data = new Gson().fromJson(reader, Data.class);' here occurs the NPE. How can I transer the data from this new Thread to my RecyclerViewAdapter? Currently I created an attribute for the InputStreamReader: 'InputStreamReader reader = null;'. – Jochen May 08 '17 at 10:55
  • 1
    you can move Data data = new Gson().fromJson(reader, Data.class); List listdata = new ArrayList(); listdata.add(data); recyclerView.setAdapter(new JSONSRecyclerViewAdapter(listdata,mListener)); in thread to avoid NPE – Pro Mode May 08 '17 at 11:00
1

We should put network call in background. You can use AsyncTask to avoid this

Context context = view.getContext();
    RecyclerView recyclerView = (RecyclerView) view;

    new AsyncTask<Void, List<Data>, List<Data>>() {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected List<Data> doInBackground(Void... params) {
            URL url = null;
            try {
                // Definition of the URL with the JSON-Strings
                url = new URL("http://www.jsoneditoronline.org?id=b1b4f5e2526ab04b562723bccae30a40");
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
            InputStreamReader reader = null;
            try {
                // InputStreamReader is responsible to open and consume the
                // URL
                reader = new InputStreamReader(url.openStream());
            } catch (IOException e) {
                e.printStackTrace();
            }
            // Conversion via GSON
            Data data = new Gson().fromJson(reader, Data.class);

            List<Data> listdata = new ArrayList<Data>();
            listdata.add(data);
            return listdata;
        }

        @Override
        protected void onPostExecute(List<Data> dataList) {

            recyclerView.setAdapter(newJSONSRecyclerViewAdapter(listdata,mListener));
        }
    }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
PEHLAJ
  • 9,980
  • 9
  • 41
  • 53
  • Thank you! I followed your approach and used Async Task. After running the app, however, I receive an error concerning the doInBackground()-method. – Maximilian Wittmann May 08 '17 at 14:16