2012-08-15 56 views
1

我做一個登錄應用程序(taken from here),基本上,我想在登錄使用的身份證號碼和密碼,將連接到一個在線數據庫,但有程序崩潰後,我加入了異步任務分成代碼。錯誤執行異步任務在這個類

public class LoginActivity extends Activity { 
Button btnLogin; 
Button btnLinkToRegister; 
EditText inputNric; 
EditText inputPassword; 
TextView loginErrorMsg; 

// Progress Dialog 
private ProgressDialog pDialog; 

// JSON Response node names 
//success is the column name of the database - KEY_SUCCESS is we create the name 
private static String KEY_SUCCESS = "success"; 
private static String KEY_ERROR = "error"; 
private static String KEY_ERROR_MSG = "error_msg"; 
private static String KEY_NAME = "name"; 
private static String KEY_NRIC = "nric"; 
private static String KEY_CREATED_AT = "created_at"; 

    @Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.login); 

    // Importing all assets like buttons, text fields 
    inputNric = (EditText) findViewById(R.id.loginNric); 
    inputPassword = (EditText) findViewById(R.id.loginPassword); 
    btnLogin = (Button) findViewById(R.id.buttonLogin); 
    btnLinkToRegister = (Button) findViewById(R.id.btnLinkToRegisterScreen); 
    loginErrorMsg = (TextView) findViewById(R.id.login_error); 

    // login button click event 
    btnLogin.setOnClickListener(new View.OnClickListener() { 

     public void onClick(View arg0) { 
      // starting background task to update case 
      new LoginUser().execute(); 
     } 
    }); 

    // Link to Register Screen 
    btnLinkToRegister.setOnClickListener(new View.OnClickListener() { 

     public void onClick(View view) { 
      Intent i = new Intent(getApplicationContext(), 
      RegisterActivity.class); 
      startActivity(i); 
      finish(); 
     } 
    }); 
} 

/** 
* Background Async Task to Login User 
* */ 
class LoginUser extends AsyncTask<String, String, String> { 

    /** 
    * Before starting background thread Show Progress Dialog 
    * */   
    protected void onPreExecute() { 
    super.onPreExecute(); 
    pDialog = new ProgressDialog(LoginActivity.this); 
    pDialog.setMessage("Logging In ..."); 
    pDialog.setIndeterminate(false); 
    pDialog.setCancelable(true); 
    pDialog.show(); 
    } 

    /** 
    * Logging in 
    * */ 
    protected String doInBackground(String... params) { 

      String nric = inputNric.getText().toString(); 
      String password = inputPassword.getText().toString(); 
      UserFunctions userFunction = new UserFunctions(); 
      Log.d("Button", "Login"); 
      JSONObject json = userFunction.loginUser(nric, password); 

      // check for login response 
      try { 
       if (json.getString(KEY_SUCCESS) != null) { 
        loginErrorMsg.setText(""); 
        String res = json.getString(KEY_SUCCESS); 
        if(Integer.parseInt(res) == 1){ 
         // user successfully logged in 
         // Store user details in SQLite Database 
         DatabaseHandler db = new DatabaseHandler(getApplicationContext()); 
         JSONObject json_user = json.getJSONObject("user"); 

         // Clear all previous data in database 
         userFunction.logoutUser(getApplicationContext()); 
         db.addUser(json_user.getString(KEY_NAME), json_user.getString(KEY_NRIC), json_user.getString(KEY_CREATED_AT));      

         // Launch home Screen 
         Intent home = new Intent(getApplicationContext(), HomeActivity.class); 

         // Close all views before launching home 
         home.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
         startActivity(home); 

         // Close Login Screen 
         finish(); 
        }else{ 
         // Error in login 
         loginErrorMsg.setText("Incorrect username/password"); 
        } 
       } 
      } catch (JSONException e) { 
       e.printStackTrace(); 
      } 
      return null; 
    } 

    /** 
    * After completing background task Dismiss the progress dialog 
    * **/ 
    protected void onPostExecute(String file_url) { 
     // dismiss the dialog once case deleted 
     pDialog.dismiss(); 

    } 
} 

} 

logcat的錯誤:

08-15 06:20:26.254: E/AndroidRuntime(302): FATAL EXCEPTION: AsyncTask #1 
08-15 06:20:26.254: E/AndroidRuntime(302): java.lang.RuntimeException: An error occured  while executing doInBackground() 
08-15 06:20:26.254: E/AndroidRuntime(302): at android.os.AsyncTask$3.done(AsyncTask.java:200) 
08-15 06:20:26.254: E/AndroidRuntime(302): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273) 
08-15 06:20:26.254: E/AndroidRuntime(302): at java.util.concurrent.FutureTask.setException(FutureTask.java:124) 
08-15 06:20:26.254: E/AndroidRuntime(302): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307) 
08-15 06:20:26.254: E/AndroidRuntime(302): at java.util.concurrent.FutureTask.run(FutureTask.java:137) 
08-15 06:20:26.254: E/AndroidRuntime(302): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068) 
08-15 06:20:26.254: E/AndroidRuntime(302): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561) 
08-15 06:20:26.254: E/AndroidRuntime(302): at java.lang.Thread.run(Thread.java:1096) 
08-15 06:20:26.254: E/AndroidRuntime(302): Caused by: android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 
08-15 06:20:26.254: E/AndroidRuntime(302): at android.view.ViewRoot.checkThread(ViewRoot.java:2802) 
08-15 06:20:26.254: E/AndroidRuntime(302): at  android.view.ViewRoot.requestLayout(ViewRoot.java:594) 
08-15 06:20:26.254: E/AndroidRuntime(302): at android.view.View.requestLayout(View.java:8125) 
08-15 06:20:26.254: E/AndroidRuntime(302): at android.view.View.requestLayout(View.java:8125) 
08-15 06:20:26.254: E/AndroidRuntime(302): at android.view.View.requestLayout(View.java:8125) 
08-15 06:20:26.254: E/AndroidRuntime(302): at android.view.View.requestLayout(View.java:8125) 
08-15 06:20:26.254: E/AndroidRuntime(302): at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:254) 
08-15 06:20:26.254: E/AndroidRuntime(302): at android.view.View.requestLayout(View.java:8125) 
08-15 06:20:26.254: E/AndroidRuntime(302): at android.widget.TextView.checkForRelayout(TextView.java:5378) 
08-15 06:20:26.254: E/AndroidRuntime(302): at android.widget.TextView.setText(TextView.java:2688) 
08-15 06:20:26.254: E/AndroidRuntime(302): at android.widget.TextView.setText(TextView.java:2556) 
08-15 06:20:26.254: E/AndroidRuntime(302): at android.widget.TextView.setText(TextView.java:2531) 
08-15 06:20:26.254: E/AndroidRuntime(302): at com.pivestigator.LoginActivity$LoginUser.doInBackground(LoginActivity.java:107) 
08-15 06:20:26.254: E/AndroidRuntime(302): at com.pivestigator.LoginActivity$LoginUser.doInBackground(LoginActivity.java:1) 
08-15 06:20:26.254: E/AndroidRuntime(302): at android.os.AsyncTask$2.call(AsyncTask.java:185) 
08-15 06:20:26.254: E/AndroidRuntime(302): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) 
08-15 06:20:26.254: E/AndroidRuntime(302): ... 4 more 
08-15 06:20:26.344: W/ActivityManager(75): Force finishing activity com.pivestigator/.LoginActivity 
08-15 06:20:28.554: E/WindowManager(302): Activity com.pivestigator.LoginActivity has leaked window [email protected] that was originally added here 
08-15 06:20:28.554: E/WindowManager(302): android.view.WindowLeaked: Activity com.pivestigator.LoginActivity has leaked window [email protected] that was originally added here 
08-15 06:20:28.554: E/WindowManager(302): at android.view.ViewRoot.<init>(ViewRoot.java:247) 
08-15 06:20:28.554: E/WindowManager(302): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148) 
08-15 06:20:28.554: E/WindowManager(302): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91) 
08-15 06:20:28.554: E/WindowManager(302): at android.view.Window$LocalWindowManager.addView(Window.java:424) 
08-15 06:20:28.554: E/WindowManager(302): at android.app.Dialog.show(Dialog.java:241) 
08-15 06:20:28.554: E/WindowManager(302): at com.pivestigator.LoginActivity$LoginUser.onPreExecute(LoginActivity.java:90) 
08-15 06:20:28.554: E/WindowManager(302): at android.os.AsyncTask.execute(AsyncTask.java:391) 
08-15 06:20:28.554: E/WindowManager(302): at com.pivestigator.LoginActivity$1.onClick(LoginActivity.java:60) 
08-15 06:20:28.554: E/WindowManager(302): at android.view.View.performClick(View.java:2408) 
08-15 06:20:28.554: E/WindowManager(302): at android.view.View$PerformClick.run(View.java:8816) 
08-15 06:20:28.554: E/WindowManager(302): at android.os.Handler.handleCallback(Handler.java:587) 
08-15 06:20:28.554: E/WindowManager(302): at android.os.Handler.dispatchMessage(Handler.java:92) 
08-15 06:20:28.554: E/WindowManager(302): at android.os.Looper.loop(Looper.java:123) 
08-15 06:20:28.554: E/WindowManager(302): at android.app.ActivityThread.main(ActivityThread.java:4627) 
08-15 06:20:28.554: E/WindowManager(302): at java.lang.reflect.Method.invokeNative(Native Method) 
08-15 06:20:28.554: E/WindowManager(302): at java.lang.reflect.Method.invoke(Method.java:521) 
08-15 06:20:28.554: E/WindowManager(302): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 
08-15 06:20:28.554: E/WindowManager(302): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 
08-15 06:20:28.554: E/WindowManager(302): at dalvik.system.NativeStart.main(Native Method) 
+0

意圖調用你應該在Handler中做我認爲這將解決你的問題。一切你在PostExecute方法中應該做的與UI相關的任務 – Anand 2012-08-15 06:43:17

+0

看起來問題可能出現在第107行,你能寫出哪一行嗎? – 2012-08-15 06:44:28

+0

線107:'UserFunctions userFunction =新UserFunctions();' – Twister 2012-08-15 06:55:39

回答

0

loginErrorMsg.setText("Incorrect username/password");移至AsyncTask'sonProgressUpdate(..)方法,並且調用publishProgress(..)而不是在doInBackground()線程中。

另一個問題是(在我看來至極導致崩潰)是您要開始從工作線程創建一個新的Activity。將下面的代碼到onPostExecute(..)方法,只是pDialog.dismiss()後,檢查那裏是否登錄過doInBackground()返回值是成功的,並onPostExecute()的說法。

泄露的窗口例外意味着,ProgressDialog仍然可見,當您嘗試完成您的acttivity。

class LoginUser extends AsyncTask<Void, String, Boolean> { 

    /** 
    * Before starting background thread Show Progress Dialog 
    * */   
    protected void onPreExecute() { 
     super.onPreExecute(); 
     pDialog = new ProgressDialog(LoginActivity.this); 
     pDialog.setMessage("Logging In ..."); 
     pDialog.setIndeterminate(false); 
     pDialog.setCancelable(true); 
     pDialog.show(); 
    } 

    /** 
    * Logging in 
    * */ 
    protected Boolean doInBackground(Void... params) { 

     String nric = inputNric.getText().toString(); 
     String password = inputPassword.getText().toString(); 
     UserFunctions userFunction = new UserFunctions(); 
     Log.d("Button", "Login"); 
     JSONObject json = userFunction.loginUser(nric, password); 

     boolean isSuccess = false; 

     // check for login response 
     try { 
      if (json.getString(KEY_SUCCESS) != null) { 
       // Set the error TextField on the UI thread 
       publishProgress(""); 

       String res = json.getString(KEY_SUCCESS); 
       if(Integer.parseInt(res) == 1){ 
        // user successfully logged in 
        // Store user details in SQLite Database 
        DatabaseHandler db = new DatabaseHandler(getApplicationContext()); 
        JSONObject json_user = json.getJSONObject("user"); 

        // Clear all previous data in database 
        userFunction.logoutUser(getApplicationContext()); 
        db.addUser(json_user.getString(KEY_NAME), json_user.getString(KEY_NRIC), json_user.getString(KEY_CREATED_AT));      


        // We logged in successfully 
        isSuccess = true; 
       }else{ 
        // Error in login 
        // Set the error TextField on the UI thread 
        publishProgress("Incorrect username/password"); 
       } 
      } 
     } catch (JSONException e) { 
      e.printStackTrace(); 
     } 
     return isSuccess; 
    } 

    @Override 
    protected void onProgressUpdate(String... values) { 
     loginErrorMsg.setText(values[0]); 
    } 

    /** 
    * After completing background task Dismiss the progress dialog 
    * **/ 
    protected void onPostExecute(Boolean result) { 
     // dismiss the dialog once case deleted 
     pDialog.dismiss(); 

     if(result.booleanValue()){ 
      // Launch home Screen 
       Intent home = new Intent(getApplicationContext(), HomeActivity.class); 

       // Close all views before launching home 
       home.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
       startActivity(home); 

       // Close Login Screen 
       finish(); 
     } 
    } 
} 
+0

可以用我的例子來編碼嗎?我真的不明白。 – Twister 2012-08-15 07:25:58

+0

我會在幾分鐘後發佈。 – 2012-08-15 07:32:34

+0

我用代碼編輯了我的答案。 'LoginUser'上的錯誤 – 2012-08-15 07:38:51

2

本身說明你要更新錯誤或不允許其他線程訪問活動的主UI線程。

實際上,您正在嘗試從AsyncTask的doInBackground()(如doInBAckground()在工作線程中運行)方法更新Activity的視圖。在Android中是不允許的。

我覺得這些線,

String nric = inputNric.getText().toString(); 
String password = inputPassword.getText().toString(); 

loginErrorMsg.setText("Incorrect username/password"); 

原因的錯誤。所以從doInBackground()的AsyncTask刪除這些行,並把這些代碼行onPreExecute()的AsyncTask的onPostExecute()

+0

我已經試過,但,當我把'字符串NRIC = inputNric.getText()的toString();在'onPreExecute()'中,String password = inputPassword.getText()。toString();''JSONObject json = userFunction.loginUser(nric,password);'有錯誤。 – Twister 2012-08-15 07:17:09

+0

**在AsyncTask類**中全局聲明字符串變量。比如''nric,password;'在'onPreExecute()'之前,在preExecute()中寫入''nric = inputNric.getText()。toString(); password = inputPassword.getText()。toString();' – user370305 2012-08-15 07:20:09

+0

它不起作用。仍然有錯誤 – Twister 2012-08-15 07:35:28