1

I've passed through all SO's solution to solve NetworkOnMainThreadException Including ASync class - but still something is wrong

Here is my simple code :

ActivityMain Class :

public class MainActivity extends Activity
{
    ArrayList<City> alCities = new ArrayList<City>();
    Activity activity=null;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        activity=this;

        new MyTask(activity, alCities).execute(); //<--- running ASYNC here
    }
}

MyTask Class :

public class MyTask extends AsyncTask<Void, Void, ArrayList<City>>
{
    ArrayList<City> alCities = null;
    Activity ac = null;

    public MyTask(Activity activity, ArrayList<City> al) //ctor
    {
        alCities = al;
        this.activity= activity;
    }

    @Override
    protected ArrayList<City> doInBackground(Void... params)
    {
        try
        {
            Object myJsonObject = Util.getJson("http://jsbin.com/lobel/2.js"); //internet job

                try
                {
                    //...fill array list...
                    return alCities;

                } catch (Exception e)
                {
                    ...
                }
            }
        } catch (Exception e)
        {
            ...
        }
        return null;
    }


    protected void onPostExecute(ArrayList<City> alCities)
    {
    ...
    //update UI
    ListView l1 = (ListView) ac.findViewById(R.id.list_view_1);
    ///
    }

}

But still :

enter image description here

nb :

If I put :

if (android.os.Build.VERSION.SDK_INT > 9) {
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
} 

It does work :

enter image description here

Question

What am I doing wrong ?

Full stack trace : http://jsbin.com/bilafi/2/edit

All I do is loading json file !

Full code of onPostExecute :

protected void onPostExecute(ArrayList<City> alCities)
    {
        CustomArrayAdapter adapter = new CustomArrayAdapter(ac, alCities);

        ListView l1 = (ListView) ac.findViewById(R.id.list_view_1);
        l1.setAdapter(adapter);
        l1.setOnItemClickListener(new OnItemClickListener()
        {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id)
            {
                // Util.Toast(getBaseContext(), "You have selected " + 1);

            }
        });
    }
Royi Namir
  • 144,742
  • 138
  • 468
  • 792
  • When examining the complete stack trace, at which line of your code does the Exception occur? Is this line inside the `doInBackground` of the AsyncTask? – nhaarman Sep 16 '14 at 20:22
  • 2
    Show the full stacktrace, and include it as text, please, not a screenshot! There must be something else you're not showing us. What else is in `onPostExecute()`? – Graham Borland Sep 16 '14 at 20:22
  • Most likely you are doing something in `onPostExecute()` that cause `okhttp` to make a network call (maybe a lazy loading call) – iTech Sep 16 '14 at 20:23
  • Edited. pasting her it also - full stack trace http://jsbin.com/bilafi/2/edit – Royi Namir Sep 16 '14 at 20:24
  • 1
    The problems comes from here com.example.listview3.Util.getBitmapFromURL(Util.java:179), nothing to do with the Json file. – Henry Sep 16 '14 at 20:28

2 Answers2

7

This is where your crash is:

at com.example.listview3.Util.getBitmapFromURL(Util.java:179)
at com.example.listview3.CustomArrayAdapter.getView(CustomArrayAdapter.java:67)

You have used the AsyncTask correctly. However, when filling the list, you're trying to fetch images, again using the network. This time, you're not using an AsyncTask, hence the NetworkOnMainThreadException.

nhaarman
  • 98,571
  • 55
  • 246
  • 278
  • But the code itself runs inside the thread no ? I also put the main call in a thread and it still occured. if A calls B and A started within thread , then B also.. – Royi Namir Sep 16 '14 at 20:27
  • 1
    The code placed in `onPostExecute` does not run in the background thread, no. You will have to start another thread for each of the images. – nhaarman Sep 16 '14 at 20:29
  • Yep, there you have it :) – nhaarman Sep 16 '14 at 20:30
  • Just a note, handling image loading for items in a `ListView` can get a bit complex. As views get recycled, you will need to keep track of your request threads to cancel them as well - otherwise you'll end up with the wrong image for a certain item. [Picasso](http://square.github.io/picasso/) is a nice library which handles this for you. – nhaarman Sep 16 '14 at 20:32
3

From the full stack trace the error source is clear at

om.example.listview3.CustomArrayAdapter.getView() where it is trying to load Bitmap from URL

i.e.at com.example.listview3.Util.getBitmapFromURL(Util.java:179)

onPostExecute runs in the main UI thread, that's why you are getting the NetworkOnMainThreadException

You might want to consider using volley, it can work on top of okhttp and provides easy to use method for loading images without threading hassles, it was introduced in Google IO 2013

Community
  • 1
  • 1
iTech
  • 18,192
  • 4
  • 57
  • 80