Android AsyncTask и исключение NetworkOnMainThreadException

Я работаю над приложением для Android, которое использует Jsoup. В начале разработки я «обходил» необходимость реализации любого типа многопоточности, потому что я просто хотел завершить большую часть кода, прежде чем приступать к многопоточности. Сейчас я пытаюсь использовать AsyncTask, но все равно получаю ошибку NetworkOnMainThreadException. Я прочитал множество руководств и сообщений SO об AsyncTask, но все же могу определить проблему. Когда я добавляю код StrictMode..., приложение работает по желанию, за исключением блокировки пользовательского интерфейса при загрузке данных с помощью Jsoup. Если бы кто-нибудь мог показать мне, что я делаю неправильно в отношении AsyncTask, я был бы признателен. (P.S. Я знаю, что есть много избыточного кода, который нужно очистить, но я хочу сначала заставить работать AsyncTask)

public void onCreate(Bundle savedInstanceState)  {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);  

            /***This is the work around used***/
            StrictMode.ThreadPolicy policy = new     StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
            /******/  



            up = new TreeMap<Double, String[]>(); 

            c1 = "example.com/1";
            //instansiate textviews (6)
                    doc1 = doc;
            c2 = "example.com/2";
            //instansiate textviews (6)
                    doc2 = doc;
            c3 = "example.com/3";
            //instansiate textviews (6)
            doc3 = doc;

            // instansiate textviews(16)

            new Download().execute(c1,c2,c3);

   } 
        private class Download extends AsyncTask<String, Integer, String[][]> {
            @Override
            protected String[][] doInBackground(String... urls){
                out = new String[7][3];
                try {
                    doc = Jsoup.connect(urls[0]).data().get();          
                    //days, times, and cs arrays created and filled

                    String[] out1arr = {days[0], times[0], cs[0]};
                    //...all 7
                    String[] out7arr = {days[6], times[6], cs[6]};
                    String[][] outarrs = {out1arr,out2arr,out3arr,out4arr,out5arr,out6arr,out7arr};
                    for (int i= 0; i < out.length; i++){
                        out[i] = outarrs[i];
                    }
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                return (out);
            }
            @Override
            protected void onProgressUpdate(Integer... progress){
            }
            @Override
            protected void onPostExecute(String[][] result){

                Do(/*textviews(6)*/, c1, a, outa, "example1"); //a is previously instantiated double array, outa is preiously instantiated string array
                Do(/*textviews(6)*/, c2, b, outb, "example2");
                Do(/*textviews(6)*/, c3, c, outc, "example3");


                upc00.setText(getUpc()[0][0]);
                //setText for all 16
                upc32.setText(getUpc()[3][2]);

            }

            private void Do(TextView t, TextView u, TextView v, TextView w, TextView x, TextView y,String webpage, double[] darr, String[] sarr, String show){


                t.setText(doInBackground(webpage)[0][0]);
                //...all 6
                y.setText(doInBackground(webpage)[1][2]);       
                for (int i =0; i < darr.length; i++){
                    darr[i] = tis[i];
                    up.put(darr[i], out[i]);
                }
            }
        }
        private ArrayList<String[]> getMap(){
                //...
            return s;
        }
        private String[][] getUpc(){
            //...
            return upc;
        }

person user1935594    schedule 29.12.2012    source источник


Ответы (1)


Фреймворк вызывает doInBackground, вы не должны вызывать его сами. Ваш код делает вызов из onPostExecute, который вызывается фреймворком в потоке пользовательского интерфейса. Таким образом, ваши вызовы выполняются в потоке пользовательского интерфейса.

Переместите всю логику выборки в метод doInBackgound. Для доставки результатов вызывающей стороне следует использовать метод onPostExecute.

person Henry    schedule 29.12.2012
comment
Спасибо. Мне нужно будет изменить много кода, но на основе предложенных вами изменений время загрузки теперь составляет ~ 1 секунду, а не 10-15, как раньше. - person user1935594; 30.12.2012