Как обновить 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();
}
}
Теперь это обновит адаптер, но добавит тот же контакт