Как обновить пользовательский интерфейс из асинтаска

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

Я использую этот код.
У меня есть обновил 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/


person Bjorn    schedule 01.06.2014    source источник
comment
postExecute() GetContacts обновляет пользовательский интерфейс, если это так, он уже запущен в потоке пользовательского интерфейса и должен работать. попробуйте предоставить больше кода   -  person Nativ    schedule 01.06.2014
comment
Я хотел спросить, первое предложение - вопрос.. ',' -› '?'   -  person Nativ    schedule 01.06.2014
comment
Похоже, вы пытаетесь обновить ListView. Если это правильно, вы должны обновить свою структуру данных и передать ее вашему адаптеру с помощью такого метода: public synchronized void refreshAdapter(List<SomeClass> itemList) { this.itemList = itemList; notifyDataSetChanged(); }   -  person Jeremy W    schedule 01.06.2014
comment
Вы обновляете URL-адрес каждые 30 секунд или каждый раз нажимаете один и тот же URL-адрес?   -  person umerk44    schedule 01.06.2014


Ответы (3)


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

  • onPreExecute()
    • runs before doInBackground()
  • onPostExecute()
    • runs after doInBackground() completes
  • onProgressUpdate()
    • this only runs when doInBackground() calls it with publishProgress()

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

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

person indivisible    schedule 01.06.2014

Вы можете использовать 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.

person Khaled Lela    schedule 01.06.2014
comment
Вам не нужно использовать runOnUiThread() в onPostExecute(). Это уже происходит. - person indivisible; 01.06.2014

Во-первых, использование 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();
            }


        }

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

person umerk44    schedule 01.06.2014