Обновление пользовательского интерфейса в AsyncTask - PullRequest
0 голосов
/ 09 мая 2011

Эй, Таким образом, после осмотра кажется, что все согласны с тем, что использование publishProgress () поможет обновить пользовательский интерфейс для более длительных вычислений. Я, кажется, реализовал это неправильно, хотя, когда я запускаю этот код, я получаю ANR. Можете ли вы помочь мне понять, почему?

Вот мой код: http://pastebin.com/zQNhkDJ9

http://pastebin.com/HcNZtAsx

Ответы [ 2 ]

1 голос
/ 09 мая 2011

Возможно, ваша проблема в том, что ваша функция doInBackground просто вызывает publishProgress. Вся ваша работа выполняется в publishProgress, который работает в потоке пользовательского интерфейса, поэтому вы все равно получите ANR таким образом. Вам нужно выполнить тяжелую работу внутри doInBackground, а затем, когда ваша обработка будет завершена, вы можете обновить поток пользовательского интерфейса.

0 голосов
/ 09 мая 2011

Вам нужно сделать свой AsyncTask статическим внутренним классом, и у него есть свойство, которое является ссылкой на вашу активность.Затем вы можете просто вызывать методы вашей Activity напрямую - как вы для UIupdate ().

Проблема, о которой вы должны знать, заключается в том, что теперь вы должны быть ОЧЕНЬ осторожны, чтобы очистить эту ссылку на свою активность в любых обратных вызовах onPause, в противном случае вы установили циклическую ссылку, и это приведет к утечкам памяти.

Мой шаблон должен иметь другой базовый Java-объект, обычно другой частный статический класс в Activity, который я называю «StateHolder», и его шлюз для обработки вещей AsyncTask, таких как его инициализация и очистка (установка в NULL) и отмена любых задач, выполняемых во время изменений ротации.В вашем обратном вызове для «onRetainNonConfigurationInstance» вы можете передать использование StateHolder в качестве выделенного объекта.

Вот примерный код:

закрытый статический класс GetConnectionsStatusTask extends AsyncTask {private BoothActivity mActivity;private Exception mReason;

public GetConnectionsStatusTask(BoothActivity activity) {
    super();
    mActivity = activity;
}

public void setActivity(BoothActivity activity) {
    mActivity = activity;
}

@Override
protected void onPreExecute() {
    if(mActivity != null) {
        mActivity.startProgressBar("Loading", "Please wait");
    }
}

@Override
protected Connections doInBackground(Void... values) {
    try {
        App app = (App)mActivity.getApplication();
        return(app.getApp().userConnections());
    }catch(Exception e) {
        mReason = e;
        return(null);
    }
}

@Override
protected void onPostExecute(Connections status) {
    super.onPostExecute(status);
    if(mActivity != null) {
        mActivity.completedConnectionsStatusCheck(status, mReason);
    }
}       
 }

закрытый статический класс StateHolder {private GetConnectionsStatusTask connectionsTask;

public void cancelTasks() {
        if (connectionsTask != null) {
            connectionsTask.setActivity(null);
            connectionsTask.cancel(true);
            connectionsTask = null;
        }
}
    public void setActivityForTasks(BoothActivity activity) {
        if (connectionsTask != null) {
            connectionsTask.setActivity(activity);
        }
}

    public void startConnections(BoothActivity activity) {
        if(mIsConnectionsChecking == false) {
            mIsConnectionsChecking = true;
            connectionsTask = new GetConnectionsStatusTask(activity);
            connectionsTask.execute();              
        }
    }
  }

Затем в onPause у меня есть код, подобный:

        if(mStateHolder != null) {
            mStateHolder.cancelTasks();
        }

И вПри создании вы можете повторно накачать ваш StateHolder следующим образом:

    Object retained = getLastNonConfigurationInstance();
    if(retained != null && retained instanceof StateHolder) {
        mStateHolder = (StateHolder) retained;
        mStateHolder.setActivityForTasks(this);
     } else {
       mStateHolder = new StateHolder();
     }

Это также приведет к повторной инициализации StateHolder с текущей активностью, чтобы вы могли заново устанавливать любые виджеты пользовательского интерфейса, такие как обновления индикатора выполнения и т. д.

Используя этот шаблон, вы фактически можете запускать асинхронные задачи и обрабатывать изменения вращения с помощью индикаторов выполнения, которые повторно инициализируют себя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...