Как обновить ui из asynctask

Я видел много примеров того, как это сделать, но я могу понять, как реализовать его в моем коде.

Я использую этот код.
Я обновил URL-адрес, поэтому он получит json с динамическими данными. То, что я пытаюсь сделать, - это автоматически обновлять список каждые 30 секунд с помощью этого кода.

Handler handler = new Handler();
    Runnable refresh = new Runnable() {
        public void run() {
            new GetContacts().execute();
            handler.postDelayed(refresh, 30000); 
        }
    };

Он обновляется и вызывает URL-адрес и получает данные, но пользовательский интерфейс не обновляется.

Спасибо за любые подсказки, которые помогают мне в правильном направлении.

http://www.androidhive.info/2012/01/android-json-parsing-tutorial/

Ответ 1

У вас есть три защищенных метода в AsyncTask, которые могут взаимодействовать с пользовательским интерфейсом.

  • onPreExecute()
    • выполняется до doInBackground()
  • onPostExecute()
    • выполняется после doInBackground() завершает
  • onProgressUpdate()
    • это выполняется только тогда, когда doInBackground() вызывает его с помощью publishProgress()

Если в вашем случае задача выполняется намного дольше, чем 30 секунд, которые вы хотите обновить, вы хотели бы использовать onProgressUpdate() и publishProgress(). В противном случае onPostExecute() должен выполнить трюк.

См. официальную документацию о том, как ее реализовать.

Ответ 2

Вы можете использовать AsycTask и обновить list ui для задачи, завершенной в onPostExecute.

    new AsyncTask<String, String, String>() {
        /**
         * Before starting background do some work.
         * */
        @Override
        protected void onPreExecute() {
        }

        @Override
        protected String doInBackground(String... params) {
            // TODO fetch url data do bg process.
            return null;
        }

        /**
         * Update list ui after process finished.
         */
        protected void onPostExecute(String result) {
               // NO NEED to use activity.runOnUiThread(), code execute here under UI thread. 

                 // Updating parsed JSON data into ListView
                 final List data = new Gson().fromJson(result);
                // updating listview
                ((ListActivity) activity).updateUI(data);
        }

    };
}

Обновление Не нужно использовать runOnUiThread внутри onPostExecute, потому что он уже вызывается, и его тело выполняется под UIThread.

Ответ 3

Первое, что используется postdelayed(), не будет запускать ваш код в повторении. Если вы хотите запустить код в повторяющемся шаблоне, используйте этот код. Это будет выполняться через каждые 5 секунд

  ScheduledExecutorService scheduleTaskExecutor = Executors.newScheduledThreadPool(5);

    /*This schedules a runnable task every second*/
    scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
      public void run() 
      {
        runOnUiThread(new Runnable(){

            @Override
            public void run() {
                // TODO Auto-generated method stub
                new GetContacts().execute();
            }

        });
      }
    }, 0, 5, TimeUnit.SECONDS);

Код, которым вы следуете, каждый раз создает новый экземпляр SimpleAdapter в postExecute(), чтобы вы снова и снова видели одни и те же данные. Поэтому, если вы хотите обновить свой адаптер, создайте экземпляр SimpleAdapter в качестве члена класса и замените postExecute() на

@Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            // Dismiss the progress dialog
            if (pDialog.isShowing())
                pDialog.dismiss();
            /**
             * Updating parsed JSON data into ListView
             * */
            if(adapter == null)
            {
                adapter = new SimpleAdapter(
                    MainActivity.this, contactList,
                    R.layout.list_item, new String[] { TAG_NAME, TAG_EMAIL,
                            TAG_PHONE_MOBILE }, new int[] { R.id.name,
                            R.id.email, R.id.mobile });

                            setListAdapter(adapter);
            }
            else
            {
                adapter.notifyDataSetChanged();
            }


        }

Теперь это обновит адаптер, но добавит тот же контакт