2015-01-01 3 views
0

Мне нужно некоторое ясное понимание того, как обработка AsyncTask произойдет в моем сценарии. У меня есть простой объект java под названием Донор.Нужно немного помочь понять этот сценарий AsyncTask

Существует активность (скажем DonorDetailActivity), которая модифицирует этот объект-донор. Модификация имеет место в AsyncTask <> (скажем DonorEditService). Итак, от DonorDetailActivity, Вызывается DOOREditService, который редактирует Донор в фоновом потоке и публикует результат для основного потока пользовательского интерфейса.

DonorDetailActivity класс

public class DonorDetailActivity extends ActionBarActivity implements AsyncTaskCallback<Donor>{ 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 

     btnEditDonor.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { //Invoke the DonorEditService 
        DonorEditService editService = new DonorEditService(DonorDetailActivity.this); 
        editService.execute(donor); 
      } 
     }); 
    } 

    //Invoked from DonorEditService.onPostExecute(DonorBase updatedDonor) 
    @Override 
    public void onAsyncTaskCompleted(Donor updatedDonor) { 
     updateUI(); //Refresh screen with updatedDonor 
    } 
} 

Все это обновление Донор код работает правильно. Теперь у меня есть ситуация, когда пользователь может позвонить по телефону донору. В этом процессе я должен обновить поле Донора, чтобы отразить дату последнего вызова. Для этого я вижу два пути. Сначала обновите Донор в фоновом потоке, а затем запустите намерение телефонного звонка или сначала запустите намерение «Телефонный звонок», а затем обновите Донор. Код мудрое что-то вроде ниже

Первого обновления, а затем Вызов

//Update Donor 
DonorEditService editService = new DonorEditService(activity); 
donor.setLastCallDate(Calendar.getInstance().getTime()); 
editService.execute(donor); 
// 
Intent phoneIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + prefix + donor.getMobileNumber())); 
activity.startActivity(phoneIntent); 

Первого звонка, а затем обновить

Intent phoneIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + prefix + donor.getMobileNumber())); 
activity.startActivity(phoneIntent); 
//Update Donor 
DonorEditService editService = new DonorEditService(activity); 
donor.setLastCallDate(Calendar.getInstance().getTime()); 
editService.execute(donor); 
// 

К счастью или к сожалению, как они работают на эмуляторе. Единственное беспокойство заключается в том, что как AsyncTask.onPostExecute() вызывается в случае, если вызывающая деятельность не находится в OnResume status. То есть он заблокирован Телефонный вызов. Кроме того, какой подход лучше; Сначала отредактируйте и вызовите; или позвоните первым и Редактировать

EDIT:

Я только что понял, от @ комментарий Darwind, что я должен был бы показать код для DonorEditService, которая на самом деле AsyncTask<DonorBase> (а не андроид Service). DonorBase - суперкласс Донора.

Вот некоторая часть DonoEditService код

public class DonorEditService extends AsyncTask<DonorBase, Void, DonorBase> { 
    public DonorEditService(Activity activity, boolean displayProgressDialog) { 
     ... 
    } 

    @Override 
    protected void onPreExecute() { 
     //Show Progress Dialog for Donor Edit process 
    } 

    @Override 
    protected DonorBase doInBackground(DonorBase... donors) { 
     //Carry out the Http request to Edit Donor on Server 
     ... 
    } 

    @Override 
    protected void onPostExecute(DonorBase updatedDonor) { 
     //Run on Main UI thread. I invoke AsyncTaskCallback from here 
     taskCallback.onAsyncTaskCompleted(updatedDonor); //taskCallback is DonorDetailActivity implementing AsyncCallback 
     ... 
    } 
} 
+0

Что такое «DonorEditService», используя эту активность? Для меня это похоже на то, что вы пропустите активность, передав ссылку на свою услугу, поэтому, когда пользователь переходит от активности, совершив телефонный звонок, Android пытается приостановить действие, но не может, поскольку это действие по-прежнему ссылается на услугу. Вероятно, поэтому это работает для обоих способов, но это явно не правильное решение. Деятельность не должна связываться с такими сервисами, как вы. – Darwind

+0

Я только что прочитал ваш вопрос. Сначала я не понял, что вы назвали свой 'AsycnTask' для' Service'. Но в основном то, что я написал выше, по-прежнему сохраняется - вы не должны хранить ссылку на свою «активность» в своей «AsyncTask». Если вы это сделаете, вы будете «утекать» ссылку, когда пользователь покидает «Активность» при создании фонотеки. Теперь, когда пользователь возвращается с phonecall, «Активность», возможно, возобновляется, но это может быть совершенно новый экземпляр «Activity», и поэтому вы пропустили первый экземпляр «Activity». Он все еще там, но не может быть достигнут, так что теперь у вас есть 2 экземпляра. – Darwind

+0

@Darwind вы предположили, что я использую AsyncTask (см. Отредактированный вопрос). Фактически, я вызываю AsyncTask из Detail Activity, и я ожидал, что Activity будет уведомляться, когда AsyncTask завершает работу, чтобы я мог обновить пользовательский интерфейс, указанный в Activity Activity. Проблема уведомления о детализации происходит из-за того, что AsyncTask (DonorEditService) закодирован в отдельном java-файле, а не как вложенный класс детальной активности. Это связано с тем, что AsyncTask вызывается из нескольких мест. Что может быть обходным путем для прохождения Детальной деятельности и причиной утечки? – Jatin

ответ

0

Ну есть много решений проблемы.

Прежде всего, я предлагаю вам не передавать в DetailActivity в качестве параметра AsyncTask, так как это приведет к утечке.

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

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

Затем, когда пользователь возвращается к вашему приложению и возобновляет DetailActivity, вам просто нужно снова «привязать» к Service и запросить, есть ли что-то, что было изменено, когда пользователь был в отъезде.

Вы можете сохранить ваш AsyncTask и вместо того, чтобы позволить DetailActivity назвать это непосредственно, сделать Service называют это непосредственно, так DetailActivity Вызовите Service и это будет вызывать через к AsyncTask.

Теперь я вижу, что вы внедрили Observer pattern для DetailActivity, чтобы получать уведомление, когда делается AsyncTask. Вместо этого «трудно связанного» шаблона Observer я бы предположил, что вы внедрили BroadcastReceiver, поэтому AsyncTask отправит «трансляции» на DetailActivity. Теперь, когда DetailActivity приостановлен (пользователь делает телефонный звонок), трансляция не будет поднята DetailActivity, но это нормально. Трансляции следует снимать, только если пользователь имеет ваше приложение в фокусе на 100% (видимо).

Извините за стену с текстом, но это несколько «продвинутый» предмет. Надеюсь, это поможет вам, если нет, я попытаюсь расширить код :-)

+0

Я попытался немного почитать «Сервис» и подумал. На самом деле, я также вижу другой вариант отмены самой AsyncTask, когда вызывающая активность вот-вот будет уничтожена (в обратном вызове OnDestroy()). В основном, сохраните ссылку на вызов AsyncTask (DonorEditService), который вызывается (например, как переменная mAsyncTask), в разделе «Детализация». Затем в этой функции детализации переопределите обратный вызов OnDestroy(), чтобы отменить AsyncTask, если он все еще работает, что-то вроде mAsyncTask.cancel (true). Спасибо за ваши ценные материалы, но я поддерживаю эту тему до завтра. – Jatin

+0

Уверен, что это тоже решение, но у меня не было впечатления, что вы не заботились о том, чтобы «AsyncTask» закончил? Если вы отмените 'AsyncTask' до его завершения, вы не сможете вызвать' updateUI() ', потому что данные, которые вы обрабатывали в' AsyncTask', не обязательно обновлялись/менялись. «Сервис» может показаться сложным предметом, но я думаю, что это то, что вам нужно :-) – Darwind

Смежные вопросы