Pracuję nad aplikacją na smartfony / tablety, używam tylko jednego pliku APK i ładuję zasoby w zależności od rozmiaru ekranu, najlepszym wyborem projektu wydaje się użycie fragmentów za pośrednictwem listy ACL.
Ta aplikacja działała dobrze, do tej pory była oparta tylko na aktywności. To jest próbna klasa pokazująca, jak obsługuję AsyncTasks i ProgressDialogs w działaniach, aby działały nawet po obróceniu ekranu lub zmianie konfiguracji w trakcie komunikacji.
Nie zmienię manifestu, aby uniknąć odtworzenia działania, jest wiele powodów, dla których nie chcę tego robić, ale głównie dlatego, że oficjalni doktorzy mówią, że nie jest to zalecane i jak dotąd radziłem sobie bez tego, więc nie polecaj tego trasa.
public class Login extends Activity {
static ProgressDialog pd;
AsyncTask<String, Void, Boolean> asyncLoginThread;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.login);
//SETUP UI OBJECTS
restoreAsyncTask();
}
@Override
public Object onRetainNonConfigurationInstance() {
if (pd != null) pd.dismiss();
if (asyncLoginThread != null) return (asyncLoginThread);
return super.onRetainNonConfigurationInstance();
}
private void restoreAsyncTask();() {
pd = new ProgressDialog(Login.this);
if (getLastNonConfigurationInstance() != null) {
asyncLoginThread = (AsyncTask<String, Void, Boolean>) getLastNonConfigurationInstance();
if (asyncLoginThread != null) {
if (!(asyncLoginThread.getStatus()
.equals(AsyncTask.Status.FINISHED))) {
showProgressDialog();
}
}
}
}
public class LoginThread extends AsyncTask<String, Void, Boolean> {
@Override
protected Boolean doInBackground(String... args) {
try {
//Connect to WS, recieve a JSON/XML Response
//Place it somewhere I can use it.
} catch (Exception e) {
return true;
}
return true;
}
protected void onPostExecute(Boolean result) {
if (result) {
pd.dismiss();
//Handle the response. Either deny entry or launch new Login Succesful Activity
}
}
}
}
Ten kod działa dobrze, mam około 10.000 użytkowników bez skarg, więc logiczne wydawało się skopiowanie tej logiki do nowego projektu opartego na fragmentach, ale oczywiście nie działa.
Oto LoginFragment:
public class LoginFragment extends Fragment {
FragmentActivity parentActivity;
static ProgressDialog pd;
AsyncTask<String, Void, Boolean> asyncLoginThread;
public interface OnLoginSuccessfulListener {
public void onLoginSuccessful(GlobalContainer globalContainer);
}
public void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
//Save some stuff for the UI State
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setRetainInstance(true);
//If I setRetainInstance(true), savedInstanceState is always null. Besides that, when loading UI State, a NPE is thrown when looking for UI Objects.
parentActivity = getActivity();
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
loginSuccessfulListener = (OnLoginSuccessfulListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnLoginSuccessfulListener");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
RelativeLayout loginLayout = (RelativeLayout) inflater.inflate(R.layout.login, container, false);
return loginLayout;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//SETUP UI OBJECTS
if(savedInstanceState != null){
//Reload UI state. Im doing this properly, keeping the content of the UI objects, not the object it self to avoid memory leaks.
}
}
public class LoginThread extends AsyncTask<String, Void, Boolean> {
@Override
protected Boolean doInBackground(String... args) {
try {
//Connect to WS, recieve a JSON/XML Response
//Place it somewhere I can use it.
} catch (Exception e) {
return true;
}
return true;
}
protected void onPostExecute(Boolean result) {
if (result) {
pd.dismiss();
//Handle the response. Either deny entry or launch new Login Succesful Activity
}
}
}
}
}
Nie mogę go użyć, onRetainNonConfigurationInstance()
ponieważ musi być wywołany z działania, a nie z fragmentu, to samo dotyczy getLastNonConfigurationInstance()
. Przeczytałem tutaj kilka podobnych pytań bez odpowiedzi.
Rozumiem, że może to wymagać trochę pracy, aby uporządkować te rzeczy we fragmentach, to powiedziawszy, chciałbym zachować tę samą podstawową logikę projektowania.
Jaki byłby właściwy sposób zachowania AsyncTask podczas zmiany konfiguracji i jeśli nadal działa, pokaż progressDialog, biorąc pod uwagę, że AsyncTask jest klasą wewnętrzną fragmentu i to sam fragment wywołuje AsyncTask. Execute ()?