Посмотрим, смогу ли я вам помочь. Итак, сначала у вас есть небольшое неправильное использование asyncTasks.
AsyncTask предназначен для выполнения короткой «фоновой» операции, которая возвращает результаты в поток пользовательского интерфейса. Поток пользовательского интерфейса является единственным потоком, который может касаться элементов пользовательского интерфейса без нарушений или сбоев должным образом.
Таким образом, типичное поведение будет
UI-Thread -> Получить пользовательский ввод
AsyncTask (Фоновая нить) -> Отправка или обработка данных, переданных в
UI-Thread -> Уведомлять пользователя об успехе / неудаче
Итак, у вас есть несколько вариантов.
1) У вашего диалогового окна «До» запускается AsyncTask
private void getUserInput(){
Session session = Session.getDefaultInstance(props,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
doBackgroundProcessing(new PasswordAuthentication(username,password));
}
});
}
private void doBackgroundProcessing(PasswordAuthentication passAuth){
if(passAuth == null || !passAuth.isSuccessful()){ //or whatever success flag they have
Log.e(TAG, "Failed to get credential token");
return;
}
//else we send it to the server it appears based on your code\
showBusyIndicator() //IF you need to block the UI from interacting while you send, NOTE* showBusyIndicator is just a method YOU would create to show one.
new PhotoSend()() {
@Override
public void onPostTask(Boolean wasSuccessful) {
//I recommend actually returning a valid result rather then Void so you know whether or not it succeeded.
if(wasSuccessful){
//close busy indicator, and notify of success
}else{
//close busy indicator, and notify of error
}
}
}
}
Другим вариантом было бы перейти к сопрограммам. Это очень удобно, так как вы можете использовать async и ожидать приостановки вашего действия.
Вот пример ожидания в диалоговом окне, чтобы вернуть имя, прежде чем двигаться вперед.
protected suspend fun getNameFromDialog(): String? = suspendCancellableCoroutine { c ->
A35Log.v(mClassTag, "getNameFromDialog")
GetTextEntryDialog.newInstance(getParamsForTextDialog(), object : ITextEntryDialogListener {
override fun onTextEntered(text: String) {
if(!c.isCompleted) {
A35Log.v(mClassTag, "User entered name: $text")
c.resume(text)
}
}
override fun onCancel(){
if(!c.isCompleted) {
A35Log.v(mClassTag, "User canceled name entry")
c.resume(null)
}
}
}).show(supportFragmentManager, mClassTag)
}
Вариант использования просто для этого примера - получение имени, затем сохранение в базе данных. Это выглядит так:
private fun saveAsDuplicateConfiguration(){
launch(UI){
setIsActionInProgress(true)
val configName = withContext(DefaultDispatcher) { getNameFromDialog() }
if(configName == null){
showFancyToast(getString(R.string.canceled), true, FancyToast.INFO)
}else{
withContext(DefaultDispatcher){
try{
withTimeout(TIMEOUT_FOR_DB_INTERACTION_MS){
A35Log.v(mClassTag, "inserting copy of config with name :$configName")
val configCopy = DeviceAndConfigurationHelper.getCopyOfConfigurationModel(mSelectedConfiguration!!)
configCopy.setConfigName(configName)
configCopy.setDeviceType(FeatureHelper.PRO_DEVICE_KEY) //todo should come from BLE eventually
if(SSDBHelper.insertConfiguration(configCopy) > 0){
showFancyToast(getString(R.string.successfully_saved), true, FancyToast.SUCCESS)
finishCurrentActivity(SSGlobals.TimeOuts.TOAST_DISPLAY_DELAY_CLOSE_MS, true)
}else{
showFancyToast(getString(R.string.error_saving_copy))
}
}
}catch (e: TimeoutCancellationException) {
showFancyToast(getString(R.string.error_timed_out) + ", " + getString(R.string.error_please_try_again_or_press_back), true, FancyToast.ERROR, "TimedOut with error: ${e.message}")
}catch(ex: JobCancellationException){
showFancyToast(getString(R.string.canceled))
}catch(ex: Exception){
showFancyToast(getString(R.string.error_saving_copy) + ", " + getString(R.string.error_please_try_again_or_press_back), true, FancyToast.ERROR, "Error deleting: ${ex.message}")
}finally {
setIsActionInProgress(false)
}
}
}
}
}
Как вы можете видеть, GetNameFromDialog - это метод блокировки и ожидания, поэтому saveAsDuplicateConfiguration не перемещается до тех пор, пока не завершится получение имени, а затем пытается использовать его.
Итак, мораль этой истории в том, что сопрограммы удивительны и допускают чистый асинхронный код, но кривая обучения крутая. Так что делай то, что тебе удобно, но «и я не могу этого подчеркнуть». Не пытайтесь выполнять диалоги и извлечение пользовательского интерфейса из AsyncTask, который будет запрашивать утечки памяти, проблемы жизненного цикла и плохое управление кодом.
Вы могли бы действительно сделать это плохо, попытавшись передать слушателя и поместить обработку в обратный вызов диалога вашего аутентификатора сеанса внутри вашей асинхронной задачи, но это могло бы с треском провалиться, потому что сборка мусора может получить этот объект, когда он выходит из метода execute так что это будет ОЧЕНЬ плохая идея.
Надеюсь, это поможет, задавайте вопросы, если у вас есть.
Счастливое кодирование.