У нас есть приложение android, работающее с использованием SDK 26. Я переписываю код для использования MVP (о котором я только что узнал).
Для некоторого контекста по моей проблеме, Вот классы, которые, я считаю, довольно стандартны для MVP:
LoginContract (представление интерфейса, интерфейс Presenter)
LoginActivity реализует LoginContract.View
LoginPresenter реализует LoginContract.Presenter
LoginModelWS
В основном проблема заключается в том, что метод onPostExecute в моем AsyncTask не является будучи призванным Эта проблема возникла с тех пор, как я реорганизовал logi c для создания экземпляра и вызова этой асинхронной задачи из Activity и в LoginModel. Asynctask выполняет SOAP вызов веб-службы на нашем сервере для проверки подлинности имени пользователя.
Поэтому я прочитал AsyncTasks и обнаружил, что это может быть вызвано множеством вещей в соответствии с правилами потоков, указанными в Класс AsyncTask:
- Класс AsyncTask должен быть загружен в потоке пользовательского интерфейса.
- Экземпляр задачи должен быть создан в потоке пользовательского интерфейса.
- execute () должен быть вызванным в потоке пользовательского интерфейса.
- , вызывающим метод doInBackground () напрямую
Я подтвердил, что мой код запускался в потоке пользовательского интерфейса, выполнив:
if (Looper.myLooper() == Looper.getMainLooper() ) // Then Print confirmation
Мой вопрос: почему не вызывается onPostExecute (), теперь я переместил код из Activity в модель?
Чтобы квалифицировать мое чтение: я прочитал код AsyncTask, я бы ответил почти на каждый вопрос StackOverflow по этой теме c и несколько блогов. До сих пор были подобные случаи, но обычно они вызывались пользователем с именем doInBackground напрямую или из потока, не являющегося пользовательским интерфейсом.
Класс LoginPresenter
public LoginPresenter(LoginContract.View mView, SharedPreferenceManager spm){
this.mView = mView;
mLoginWS = new LoginModel();
}
public void doLogin(String encodedBarcodeScan) {
String[] userPass = getUserNameAndPassFromScanString(encodedBarcodeScan);
if (userPass == null || userPass.length != 2){
mView.showErrorWithBarcodeScan();
}
else {
mLoginModel.doLogin(userPass[0], userPass[1]);
}
}
Класс LoginContract
public interface LoginContract {
interface View {
void showErrorWithBarcodeScan();
void redirectToMainMenu();
void showLoginError();
}
interface Presenter {
void doLogin(String encodedBarcodeScan);
}
}
Класс LoginModel
public String authenticateLogin(final String userName, final String password, final String url)
{
authenticationResponse = null;
ModelCRUDRequest request = WebServiceUtil.getModelCrudRequest();
request.ADLoginRequest = WebServiceUtil.getADLoginRequest(userName, password);
ModelADServiceSoapBinding binding = new ModelADServiceSoapBinding(new IServiceEvents() {
@Override
public void Starting()
{
}
@Override
public void Completed(OperationResult result) // THIS CODE IS NEVER REACHED
{
WindowTabData response = (WindowTabData) result.Result;
if (response == null){
authenticationResponse = WebServiceResponseMessage.CONNECTION_ERROR;
}
else if (response != null && response.Error != null && response.Error.length() > 0)
{
authenticationResponse = WebServiceResponseMessage.SERVER_ERROR + response.Error;
}
else
{
try
{
if (response.NumRows > 0)
{
// successful login
authenticationResponse = WebServiceResponseMessage.LOGIN_AUTHENTICATED;
}
else
{
authenticationResponse = WebServiceResponseMessage.LOGIN_FAILED;
}
}
catch (Exception e)
{
authenticationResponse = WebServiceResponseMessage.EXCEPTION + e.getMessage();
}
}
}
}, url);
try
{
if (Looper.myLooper() == Looper.getMainLooper()){
Log.d("Thread", "UI Thread");
}
binding.queryDataAsync(request);
}
catch (Exception e)
{
authenticationResponse = WebServiceResponseMessage.EXCEPTION + e.getMessage();
}
}
ModelADServiceSoapBinding executeAsyn c метод (вызывается, когда мы запускаем binding.queryDataAsyn c ())
protected <T> android.os.AsyncTask<Void, Void, OperationResult<T>> executeAsync(final Functions.IFunc<T> func,
final String methodName)
{
if (Looper.myLooper() == Looper.getMainLooper()){
// This is equal
}
return new android.os.AsyncTask<Void, Void, OperationResult<T>>() {
@Override
protected void onPreExecute()
{
callback.Starting();
// This is being hit
};
@Override
protected OperationResult<T> doInBackground(Void... params)
{
OperationResult<T> result = new OperationResult<T>();
try
{
result.MethodName = methodName;
result.Result = func.Func();
WindowTabData wtd = (WindowTabData)result.Result;
ADLoginResponse loginResponse = wtd.ADLoginResponse;
// This works without exceptions
}
catch (Exception ex)
{
ex.printStackTrace();
result.Exception = ex;
}
return result; // This gets hit
}
@Override
protected void onPostExecute(OperationResult<T> result)
{
Log.d("CallBack", "Callback"); // **THIS IS NEVER CALLED**
callback.Completed(result);
}
}.execute();
}
На данный момент, я, вероятно, исчерпал свой мозг. MVP будет быстро заброшен, если мне придется потратить на это еще один день, поэтому, если какой-нибудь герой сможет пролить свет на это, я был бы очень признателен.