Tôi sẽ đóng góp cách tiếp cận của tôi để xử lý vấn đề xoay vòng này. Điều này có thể không liên quan đến OP vì anh ta không sử dụng AsyncTask
, nhưng có thể những người khác sẽ thấy nó hữu ích. Nó khá đơn giản nhưng dường như nó làm được việc cho tôi:
Tôi có một hoạt động đăng nhập với một AsyncTask
lớp lồng nhau được gọi là BackgroundLoginTask
.
Theo tôi, BackgroundLoginTask
tôi không làm bất cứ điều gì khác thường ngoại trừ việc thêm một kiểm tra null khi gọi lệnh ProgressDialog
bãi nhiệm:
@Override
protected void onPostExecute(Boolean result)
{
if (pleaseWaitDialog != null)
pleaseWaitDialog.dismiss();
[...]
}
Điều này là để xử lý trường hợp tác vụ nền kết thúc trong khi Activity
không nhìn thấy được và do đó, hộp thoại tiến trình đã bị onPause()
phương thức loại bỏ .
Tiếp theo, trong Activity
lớp cha mẹ của tôi , tôi tạo các thẻ điều khiển tĩnh toàn cục cho AsyncTask
lớp của tôi và của tôi ProgressDialog
(cái AsyncTask
, được lồng nhau, có thể truy cập các biến này):
private static BackgroundLoginTask backgroundLoginTask;
private static ProgressDialog pleaseWaitDialog;
Điều này phục vụ hai mục đích: Thứ nhất, nó cho phép tôi Activity
luôn truy cập vào AsyncTask
đối tượng ngay cả từ một hoạt động mới, xoay vòng. Thứ hai, nó cho phép tôi BackgroundLoginTask
truy cập và loại bỏProgressDialog
ngay cả sau khi xoay.
Tiếp theo, tôi thêm phần này vào onPause()
, làm cho hộp thoại tiến trình biến mất khi chúng ta Activity
rời khỏi nền trước (ngăn chặn sự cố "buộc đóng" xấu xí đó):
if (pleaseWaitDialog != null)
pleaseWaitDialog.dismiss();
Cuối cùng, tôi có những điều sau đây trong onResume()
phương pháp của mình :
if ((backgroundLoginTask != null) && (backgroundLoginTask.getStatus() == Status.RUNNING))
{
if (pleaseWaitDialog != null)
pleaseWaitDialog.show();
}
Điều này cho phép Dialog
xuất hiện lại sau khi Activity
được tạo lại.
Đây là toàn bộ lớp học:
public class NSFkioskLoginActivity extends NSFkioskBaseActivity {
private static BackgroundLoginTask backgroundLoginTask;
private static ProgressDialog pleaseWaitDialog;
private Controller cont;
// This is the app entry point.
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (CredentialsAvailableAndValidated())
{
//Go to main menu and don't run rest of onCreate method.
gotoMainMenu();
return;
}
setContentView(R.layout.login);
populateStoredCredentials();
}
//Save current progress to options when app is leaving foreground
@Override
public void onPause()
{
super.onPause();
saveCredentialsToPreferences(false);
//Get rid of progress dialog in the event of a screen rotation. Prevents a crash.
if (pleaseWaitDialog != null)
pleaseWaitDialog.dismiss();
}
@Override
public void onResume()
{
super.onResume();
if ((backgroundLoginTask != null) && (backgroundLoginTask.getStatus() == Status.RUNNING))
{
if (pleaseWaitDialog != null)
pleaseWaitDialog.show();
}
}
/**
* Go to main menu, finishing this activity
*/
private void gotoMainMenu()
{
startActivity(new Intent(getApplicationContext(), NSFkioskMainMenuActivity.class));
finish();
}
/**
*
* @param setValidatedBooleanTrue If set true, method will set CREDS_HAVE_BEEN_VALIDATED to true in addition to saving username/password.
*/
private void saveCredentialsToPreferences(boolean setValidatedBooleanTrue)
{
SharedPreferences settings = getSharedPreferences(APP_PREFERENCES, MODE_PRIVATE);
SharedPreferences.Editor prefEditor = settings.edit();
EditText usernameText = (EditText) findViewById(R.id.editTextUsername);
EditText pswText = (EditText) findViewById(R.id.editTextPassword);
prefEditor.putString(USERNAME, usernameText.getText().toString());
prefEditor.putString(PASSWORD, pswText.getText().toString());
if (setValidatedBooleanTrue)
prefEditor.putBoolean(CREDS_HAVE_BEEN_VALIDATED, true);
prefEditor.commit();
}
/**
* Checks if user is already signed in
*/
private boolean CredentialsAvailableAndValidated() {
SharedPreferences settings = getSharedPreferences(APP_PREFERENCES,
MODE_PRIVATE);
if (settings.contains(USERNAME) && settings.contains(PASSWORD) && settings.getBoolean(CREDS_HAVE_BEEN_VALIDATED, false) == true)
return true;
else
return false;
}
//Populate stored credentials, if any available
private void populateStoredCredentials()
{
SharedPreferences settings = getSharedPreferences(APP_PREFERENCES,
MODE_PRIVATE);
settings.getString(USERNAME, "");
EditText usernameText = (EditText) findViewById(R.id.editTextUsername);
usernameText.setText(settings.getString(USERNAME, ""));
EditText pswText = (EditText) findViewById(R.id.editTextPassword);
pswText.setText(settings.getString(PASSWORD, ""));
}
/**
* Validate credentials in a seperate thread, displaying a progress circle in the meantime
* If successful, save credentials in preferences and proceed to main menu activity
* If not, display an error message
*/
public void loginButtonClick(View view)
{
if (phoneIsOnline())
{
EditText usernameText = (EditText) findViewById(R.id.editTextUsername);
EditText pswText = (EditText) findViewById(R.id.editTextPassword);
//Call background task worker with username and password params
backgroundLoginTask = new BackgroundLoginTask();
backgroundLoginTask.execute(usernameText.getText().toString(), pswText.getText().toString());
}
else
{
//Display toast informing of no internet access
String notOnlineMessage = getResources().getString(R.string.noNetworkAccessAvailable);
Toast toast = Toast.makeText(getApplicationContext(), notOnlineMessage, Toast.LENGTH_SHORT);
toast.show();
}
}
/**
*
* Takes two params: username and password
*
*/
public class BackgroundLoginTask extends AsyncTask<Object, String, Boolean>
{
private Exception e = null;
@Override
protected void onPreExecute()
{
cont = Controller.getInstance();
//Show progress dialog
String pleaseWait = getResources().getString(R.string.pleaseWait);
String commWithServer = getResources().getString(R.string.communicatingWithServer);
if (pleaseWaitDialog == null)
pleaseWaitDialog= ProgressDialog.show(NSFkioskLoginActivity.this, pleaseWait, commWithServer, true);
}
@Override
protected Boolean doInBackground(Object... params)
{
try {
//Returns true if credentials were valid. False if not. Exception if server could not be reached.
return cont.validateCredentials((String)params[0], (String)params[1]);
} catch (Exception e) {
this.e=e;
return false;
}
}
/**
* result is passed from doInBackground. Indicates whether credentials were validated.
*/
@Override
protected void onPostExecute(Boolean result)
{
//Hide progress dialog and handle exceptions
//Progress dialog may be null if rotation has been switched
if (pleaseWaitDialog != null)
{
pleaseWaitDialog.dismiss();
pleaseWaitDialog = null;
}
if (e != null)
{
//Show toast with exception text
String networkError = getResources().getString(R.string.serverErrorException);
Toast toast = Toast.makeText(getApplicationContext(), networkError, Toast.LENGTH_SHORT);
toast.show();
}
else
{
if (result == true)
{
saveCredentialsToPreferences(true);
gotoMainMenu();
}
else
{
String toastText = getResources().getString(R.string.invalidCredentialsEntered);
Toast toast = Toast.makeText(getApplicationContext(), toastText, Toast.LENGTH_SHORT);
toast.show();
}
}
}
}
}
Tôi không có nghĩa là một nhà phát triển Android dày dạn, vì vậy hãy bình luận.