2016-03-23 10 views
0

私はアンドロイドアプリの基本的なログイン画面を実装しようとしています。
1)ユーザーがログイン情報を入力してヒットします。
2)AsyncTaskを拡張するLoginRequestが作成され、実行されます。
3)doInBackgroundは、いくつかのhttpを発射しますが、ユーザーの資格情報
4)onPostExecuteloginResults
5)UIスレッドは、ログイン結果を見て、それに応じて続けて設定するために呼び出さ取得する必要がありますを検証するために呼び出します。AsyncTask onPostExecute is not 'が呼び出されています

私は根本的な問題になるようにコードを単純化していますが、これまでのところ運がなかったわけです。ここには、問題を再現している簡略化されたコードがあります。私の活動インサイド

private void tryLogin(String email, String password) 
{ 
    this.showProgress(true); 
    LoginHelper loginHelper = new LoginHelper(); 
    LoginResult result = loginHelper.tryLogin(email, password); 
    this.showProgress(false); 
} 

これは、クリックリスナーに私の提出ボタンから呼び出されます。

インサイドLoginHelper:

TestClass test = new TestClass(); 
public LoginResult tryLogin(String mobileNumber, String password, int deviceId) 
{ 
    String loginUrl = "..."; 
    new LoginRequest(test).execute(loginUrl); 

    while (test.result == null) 
    { 
     try { 
      Thread.sleep(1000); 
     } 
     catch (Exception e) 
     { 
      //... 
     } 
    } 
    return test.result; 
} 

これはAsyncTaskを実行し、結果が継続されて待ちます。

LoginRequest:

public class LoginRequest extends AsyncTask<String, Void, LoginResult> 
    TestClass test; 

    public LoginRequest(TestClass test) 
    { 
     this.test = test; 
    } 
    @Override 
    protected LoginResult doInBackground(String... params) { 

     LoginResult ret = null; 
     ret = new LoginResult(1,"test"); 
     return ret; 
    } 

    @Override 
    protected void onPostExecute(LoginResult result) { 
     this.test.result = result; 
    } 
} 

私はdoInBackgroundonPostExecute内部のブレークポイントでデバッガを介してこれを実行します。 doInBackgroundが正常に実行され、の値が返されますが、onPostExecuteのブレークポイントは決してヒットしません。コードはwhileループでLoginHelperに待機します。

+0

onPostExecute()が呼び出されなかった場合に実行される次のステートメントはどれですか? –

+0

このリンクをチェックすると、http://nads-rosun.blogspot.in/2014/01/android-login-application-using.html – AmeeJoshi

+0

@AlokGupta LoginHelperのwhileループはテストを継続して待機します。結果を設定する。 –

答えて

0

基本的に、LoginRequestの変数 'result'を全体的にチェックしています。しかし、それはAsyncTaskがどのように動作するかではありません。 Docsから

AsyncTaskはあなたのユーザー インターフェイス上で、非同期の作業を実行することができます。ワーカースレッドでブロッキング操作を実行し、 は、 スレッドやハンドラを自分で処理する必要なく、結果をUIスレッドにパブリッシュします。

あなたはdoInBackground()方法で作業を行うことができますし、onPostExecute()にあなたの結果を公開します。

要素を変更したり、結果を表示したりするために、UIスレッドでonPostExecuteが実行されます。あなたの問題は、tryLogin()のチェックメソッドでUIスレッドをブロックしていることです。

それで解決方法は?

チェック方法削除:AsyncTaskで

public void tryLogin(String mobileNumber, String password, int deviceId) 
{ 
    // Starts AsynTasks, handle results there 
    String loginUrl = "..."; 
    new LoginRequest().execute(loginUrl); 
} 

public class LoginRequest extends AsyncTask<String, Void, LoginResult> 

    // Removed Constructor, if you need to pass some other variables, add it again 

    @Override 
    protected LoginResult doInBackground(String... params) { 

     // TODO: Change this to actual Http Request 
     LoginResult ret = null; 
     ret = new LoginResult(1, "test"); 
     return ret; 
    } 

    @Override 
    protected void onPostExecute(LoginResult result) { 
     // Now the result arrived! 
     // TODO: Use the result 
    } 
} 

もっと思考:

  1. あなたはおそらく、ユーザーの資格情報を保存したいの。その場合は、安全であることを確認してください。 Link
  2. 結果によっては、一部のUIを変更したい場合があります。ここでは例です:

AsyncTask:私は、コードをテストしたdidntの

new LoginRequest(loginActivity).execute(loginUrl); 

パブリッククラスLoginRequestはAsyncTask

private Activity activity; 

    // Constructor 
    public LoginRequest(Activity activity) { 
     this.activity = activity; 
    } 

    @Override 
    protected LoginResult doInBackground(String... params) { 

     // TODO: Change this to actual Http Request 
     LoginResult ret = null; 
     ret = new LoginResult(1, "test"); 
     return ret; 
    } 

    @Override 
    protected void onPostExecute(LoginResult result) { 

     ActivityLogin acLogin = (ActivityLogin) activity; 

     if(result.equals("ok")) { 
      Button loginButton = (Button) acLogin.findViewById(R.id.login-button); 
      loginButton.setBackgroundColor(Color.GREEN); 

      //Finish LoginActivity 
      acLogin.finish(); 
     } 
     else { 
      //TODO: Fail Handling 
     } 
    } 
} 

そして、このようにそれを起動を拡張します。

+0

ありがとう!主な問題は、UIThreadから呼び出されたonPostexecuteが、値の設定を待つことなく、代わりにLoginActivityでコールバックを呼び出すことで呼び出されることを認識できなかったことです。 –

+0

@ n8.premo喜んでそれは助け:) –

0

これはAsyncTaskだから、LoginRequestとwhile(test.result)を同時に呼び出している。 test.resultがまだ返されていないため、whileループに陥ってしまいました。 test.resultはonPostExecute()で行われるため、その関数内でwhileループを動かすと、関数が動作し、onPostExecute()が呼び出されます。この問題を解決する1つの方法は、コールバックインターフェイスを実装することです。 whileループをオーバーライドされたコールバックメソッドに置きます。 ここに私の答えを参照してください:how to send ArrayList(Bitmap) from asyncTask to Fragment and use it in Arrayadapter

+0

あなたのコメントを誤解しているかもしれませんが、whileループは止まっていません。ループは、test.resultがnullでないかどうかをチェックします。ヌルであるため、スレッドは1秒間スリープして再試行します。ブレークポイントをスティックしていると、スリープしていることがわかります。ループがブロックしていた場合、この時点でAsyncTaskを続けるべきではありませんか? –

0

はこの

public class LoginRequest extends AsyncTask<String, Void, LoginResult> 
    { 
    TestClass test; 
     LoginResult ret = null; 

    public LoginRequest(TestClass test) 
    { 
     this.test = test; 
    } 
    @Override 
    protected Boolean doInBackground(String... params) { 
     ret = new LoginResult(1,"test"); 
     return true; 
    } 

    @Override 
    protected void onPostExecute(Boolean success) { 
     if(success) 
      this.test.result = result; 
    } 
    } 
+0

私はそれを試してみましたが、残念ながら私は同じ結果を得ました。doInBackgroundは実行されますが、onPostExecuteは決して呼び出されません。 –

+0

何かエラーがスローされたか、デバッグポインタがdoInBackground()の後に移動する場所を確認してください –

0

一時的な解決策を試してください:あなたはdoInbackground()方法でthis.test.result = result;を追加することができます。

@Override 
protected LoginResult doInBackground(String... params) { 

      LoginResult ret = null; 
      ret = new LoginResult(1, "test"); 
      this.test.result = result; 
      return ret; 
} 

適切な解決方法を得るには完全なコードを記入してください。

関連する問題